| … | |
… | |
| 24 | =cut |
24 | =cut |
| 25 | |
25 | |
| 26 | use strict; |
26 | use strict; |
| 27 | use warnings; |
27 | use warnings; |
| 28 | #use Apache::DB; |
28 | #use Apache::DB; |
| 29 | use Date::Format; |
29 | use DateTime; |
| 30 | use Date::Parse; |
|
|
| 31 | use Errno; |
30 | use Errno; |
| 32 | use File::Path qw(rmtree); |
31 | use File::Path qw(rmtree); |
| 33 | use Carp; |
32 | use Carp; |
| 34 | |
33 | |
| 35 | use constant MKDIR_ATTEMPTS => 10; |
34 | use constant MKDIR_ATTEMPTS => 10; |
|
|
35 | |
|
|
36 | # "standard" WeBWorK date/time format (for set definition files): |
|
|
37 | # %m/%d/%y at %I:%M%P |
|
|
38 | # where: |
|
|
39 | # %m = month number, starting with 01 |
|
|
40 | # %d = numeric day of the month, with leading zeros (eg 01..31) |
|
|
41 | # %y = year (2 digits) |
|
|
42 | # %I = hour, 12 hour clock, leading 0's) |
|
|
43 | # %M = minute, leading 0's |
|
|
44 | # %P = am or pm (Yes %p and %P are backwards :) |
|
|
45 | use constant DATE_FORMAT => "%m/%d/%y at %I:%M%P"; |
| 36 | |
46 | |
| 37 | our @EXPORT = (); |
47 | our @EXPORT = (); |
| 38 | our @EXPORT_OK = qw( |
48 | our @EXPORT_OK = qw( |
| 39 | runtime_use |
49 | runtime_use |
| 40 | readFile |
50 | readFile |
| … | |
… | |
| 246 | |
256 | |
| 247 | ################################################################################ |
257 | ################################################################################ |
| 248 | # Date/time processing |
258 | # Date/time processing |
| 249 | ################################################################################ |
259 | ################################################################################ |
| 250 | |
260 | |
|
|
261 | =head2 Date/time processing |
|
|
262 | |
|
|
263 | =over |
|
|
264 | |
|
|
265 | =item $dateTime = parseDateTime($string, $display_tz) |
|
|
266 | |
|
|
267 | Parses $string as a datetime. If $display_tz is given, $string is assumed to be |
|
|
268 | in that timezone. Otherwise, the server's timezone is used. The result, |
|
|
269 | $dateTime, is an integer UNIX datetime (epoch) in the server's timezone. |
|
|
270 | |
|
|
271 | =cut |
|
|
272 | |
|
|
273 | sub parseDateTime($;$) { |
|
|
274 | my ($string, $display_tz) = @_; |
|
|
275 | $display_tz ||= "local"; |
|
|
276 | warn "parseDateTime('$string', '$display_tz')\n"; |
|
|
277 | |
|
|
278 | # Method #1: using Date::Parse |
|
|
279 | use Date::Parse; |
|
|
280 | $string =~ s/\s*\bat\b\s*/ /; # Date::Parse can't handle the "at" in WeBWorK datetimes. |
|
|
281 | my $epoch = str2time($string); |
|
|
282 | #warn "\tMethod #1: str2time($string) = $epoch\n"; |
|
|
283 | my $dt = DateTime->from_epoch(epoch => $epoch, time_zone => "local"); |
|
|
284 | #warn "\tMethod #1: \$dt = ", $dt->strftime(DATE_FORMAT." %Z"), "\n"; |
|
|
285 | |
|
|
286 | # Method #2: using Date::Manip |
|
|
287 | #use Date::Manip; |
|
|
288 | #my $dm = ParseDateString($string); |
|
|
289 | #warn "\tMethod #2: ParseDateString($string) = $dm\n"; |
|
|
290 | #use DateTime::Format::DateManip; |
|
|
291 | #my $dt = DateTime::Format::DateManip->parse_datetime($dm); |
|
|
292 | #warn "\tdMethod #2: \$dt = ", $dt->strftime(DATE_FORMAT." %Z"), "\n"; |
|
|
293 | |
|
|
294 | my $dt2 = $dt->clone->set_time_zone("floating")->set_time_zone($display_tz); |
|
|
295 | #warn "\t\$dt2 = ", $dt2->strftime(DATE_FORMAT." %Z"), "\n"; |
|
|
296 | my $epoch2 = $dt2->epoch; |
|
|
297 | #warn "\t\$epoch2 (return value) = $epoch2\n"; |
|
|
298 | |
|
|
299 | return $epoch2; |
|
|
300 | } |
|
|
301 | |
|
|
302 | =item $string = formatDateTime($dateTime, $display_tz) |
|
|
303 | |
|
|
304 | Formats the UNIX datetime $dateTime in the standard WeBWorK datetime format. |
|
|
305 | $dateTime is assumed to be in the server's time zone. If $display_tz is given, |
|
|
306 | the datetime is converted from the server's timezone to the timezone specified. |
|
|
307 | |
|
|
308 | =cut |
|
|
309 | |
| 251 | sub formatDateTime($) { |
310 | sub formatDateTime($;$) { |
| 252 | my $dateTime = shift; |
311 | my ($dateTime, $display_tz) = @_; |
| 253 | # "standard" WeBWorK date/time format (for set definition files): |
312 | $display_tz ||= "local"; |
| 254 | # %m month number, starting with 01 |
313 | #warn "formatDateTime('$dateTime', '$display_tz')\n"; |
| 255 | # %d numeric day of the month, with leading zeros (eg 01..31) |
314 | |
| 256 | # %y year (2 digits) |
315 | my $dt = DateTime->from_epoch(epoch => $dateTime, time_zone => $display_tz); |
| 257 | # %I hour, 12 hour clock, leading 0's) |
316 | #warn "\t\$dt = ", $dt->strftime(DATE_FORMAT." %Z"), "\n"; |
| 258 | # %M minute, leading 0's |
317 | return $dt->strftime(DATE_FORMAT); |
| 259 | # %P am or pm (Yes %p and %P are backwards :) |
|
|
| 260 | #return time2str("%m/%d/%y %I:%M%P", $dateTime); |
|
|
| 261 | return time2str("%m/%d/%y at %I:%M%P", $dateTime); |
|
|
| 262 | } |
318 | } |
| 263 | |
319 | |
| 264 | sub parseDateTime($) { |
320 | =item $string = textDateTime($string_or_dateTime) |
| 265 | my $string = shift; |
321 | |
| 266 | # need to bring our string from "%m/%d/%y at %I:%M%P" to "%m/%d/%y %I:%M%P" format. |
322 | Accepts a UNIX datetime or a formatted string, returns a formatted string. |
| 267 | $string =~ s/\bat\b/ /; |
323 | |
| 268 | return str2time($string); |
324 | =cut |
| 269 | } |
|
|
| 270 | |
325 | |
| 271 | sub textDateTime($) { |
326 | sub textDateTime($) { |
| 272 | return ($_[0] =~ m/^\d*$/) ? formatDateTime($_[0]) : $_[0]; |
327 | return ($_[0] =~ m/^\d*$/) ? formatDateTime($_[0]) : $_[0]; |
| 273 | } |
328 | } |
| 274 | |
329 | |
|
|
330 | =item $dateTIme = intDateTime($string_or_dateTime) |
|
|
331 | |
|
|
332 | Accepts a UNIX datetime or a formatted string, returns a UNIX datetime. |
|
|
333 | |
|
|
334 | =cut |
|
|
335 | |
| 275 | sub intDateTime($) { |
336 | sub intDateTime($) { |
| 276 | return ($_[0] =~ m/^\d*$/) ? $_[0] : parseDateTime($_[0]); |
337 | return ($_[0] =~ m/^\d*$/) ? $_[0] : parseDateTime($_[0]); |
| 277 | } |
338 | } |
|
|
339 | |
|
|
340 | =back |
|
|
341 | |
|
|
342 | =cut |
| 278 | |
343 | |
| 279 | ################################################################################ |
344 | ################################################################################ |
| 280 | # Logging |
345 | # Logging |
| 281 | ################################################################################ |
346 | ################################################################################ |
| 282 | |
347 | |