in reply to Human-readable date format strings

Answering my own question here, this turned out not to be such a big deal. For anyone interested in the future, here is the translate_date_format() function I came up with, and a Test script to demonstrate it:

#!/usr/bin/perl sub translate_date_format { my @tr = ( 'yyyy' => '%Y', 'yy' => '%y', 'mmmm' => '%B', 'mmm' => '%b', 'mm' => '%m', 'dddd' => '%A', 'ddd' => '%a', 'dd' => '%d', 'd' => '%e', 'HH' => '%H', #(%I if am/pm is specified) 'H' => '%k', #(%l if am/pm is specified) 'MM' => '%M', 'AM' => '%p', 'PM' => '%p', 'am' => '%P', 'pm' => '%P', 'SS' => '%S', ); local $_ = shift; for ( my $i = 0; $i <= $#tr; $i += 2 ) { s/(?<!%)$tr[$i]/$tr[$i+1]/g +; } s/%H(.*?%[pP])/%I$1/g; s/%k(.*?%[pP])/%l$1/g; return ( $_ ); } ### Test ############################################################# +######### use POSIX; use Time::Piece; my @test = ( 'yyyy-mm-dd', 'd/mm/yy', 'H:MM:SSAM', 'HH:MM:SSpm', 'mmm ddd, yy', 'dddd, mmmm dd, yyyy HH:MM:SS', ); foreach ( @test ) { my $tdf = translate_date_format ( $_ ); print "$_ => $tdf\n"; my $date = POSIX::strftime ( $tdf, localtime() ); print " POSIX: $date\n"; my $t = localtime(); my $date = $t->strftime ( $tdf ); print " Time::Piece: $date"; $date = $t->strptime ( $date, $tdf ); print " => $date\n"; }

Replies are listed 'Best First'.
Re^2: Human-readable date format strings
by Tux (Canon) on Oct 21, 2014 at 06:17 UTC
    • Why use an array and not a hash?
    • You are missing "m" (month, no leading zero - maybe "%e")
    • You are missing "w" (day of week: "%w" or "%u")
    • You are missing "ww" (week: "%V" or "%U")
    • You are missing "M" (minute, no leading zero)
    • You are missing "+hhmm" (time zone: "%z")
    • You are missing "+hh:mm" (time zone: "%:z")
    • You are missing "+hh:mm:ss" (time zone: "%::z")

    In many of these human readable formats, "A" is considered AM/PM

    In some (many?) lower case "h" is considered the shortcut for 12-hour version of "H" (likewise for "hh" vs "HH")

    What do you do with "yyy"? Leave it as is?

    Is having "ZZZ" a suggestion for time zone abbreviation "%Z"?

    Is having "j" or "ddddd" or maybe even "d#" a suggestion for day of year ("%j")?


    Enjoy, Have FUN! H.Merijn
      Why use an array and not a hash?

      Because the order matters. If the regex checked for 'yy' before 'yyyy', then 'yyyy-mm-dd' would translate to '%y%y-%m-%d'.

      You are missing...

      I can only do what the POSIX standard supports. Thanks for the translation suggestions, they are easy enough to add.

      What do you do with "yyy"? Leave it as is?

      Like POSIX::strftime(), anything not recognized as a formatting element is left as-is, yes (although 'yyy' in specific would translate to '%yy'). Unlike strftime(), I didn't add an escape sequence in case you wanted a literal 'yy' in the string. Exercise for the user I guess. :-)

         Because the order matters. If the regex checked for 'yy' before 'yyyy', then 'yyyy-mm-dd' would translate to '%y%y-%m-%d'.

        use warnings; sub translate_date_format { my %tr = ( yyyy => "%Y", yy => "%y", mmmm => "%B", mmm => "%b", mm => "%m", m => "%e", ww => "%V", # or %U w => "%w", # or %u j => "%j", dddd => "%A", ddd => "%a", dd => "%d", d => "%e", HH => "%H", H => "%k", hh => "%I", h => "%i", MM => "%M", A => "%p", AM => "%p", PM => "%p", a => "%P", am => "%P", pm => "%P", SS => "%S", ZZZ => "%Z", ); my $str = shift; $str =~ s/(?<!%)$_/$tr{$_}/g for reverse sort keys %tr; return ($str); } ### Test ############################################################# +######### use POSIX; use Time::Piece; my @test = ( "yyyy-mm-dd", "d/mm/yy", "H:MM:SSAM", "HH:MM:SSpm", "mmm ddd, yy", "dddd, mmmm dd, yyyy HH:MM:SS", ); foreach (@test) { my $tdf = translate_date_format ($_); print "$_ => '$tdf'\n"; my $date = POSIX::strftime ($tdf, localtime ()); print " POSIX: $date\n"; my $t = localtime (); $date = $t->strftime ($tdf); print " Time::Piece: $date"; $date = $t->strptime ($date, $tdf); print " => $date\n"; }

        I also see (using warnings) yet another reason never to use AM/PM :) :

        HH:MM:SSpm => '%H:%M:%S%P' POSIX: 11:39:52am garbage at end of string in strptime: am at /pro/lib/perl5/site_perl/5 +.20.0/x86_64-linux-thread-multi-ld/Time/Piece.pm line 469. Time::Piece: 11:39:52am => Thu Jan 1 11:39:52 1970

        Enjoy, Have FUN! H.Merijn