marek1703 has asked for the wisdom of the Perl Monks concerning the following question:

Hallo dear Perl Monks!

I wish you a happy new Year 2015! Hoping you will share your wisdom as you did last year.

I have a huge file of SMS Messages (Macintosh) where I need to transform the timestamps into human readable dates. I did not captured well, how to calculate the daylight savings ...

While copying and pasting many many SMS into my file to make a perl script working on it, I am very proud of my poor programming skills, until there is a message popping up claiming to be sent at 12:12 - but the calculated time is 11:12 :-(

Here my example script. Thank you for your insight!

marek

#! /usr/bin/perl # I am trying to convert the seconds of the sms database into a # reasonable date. # But there is a problem left: the daylight saving time (Sommerzeit vs + Winterzeit) use warnings; use strict; use Date::Calc qw(Localtime Day_of_Week Day_of_Week_to_Text); my %date_pairs = ( 391263207 => "Sonntag, 26.05.2013 - 13:13:27", 410000659 => "Sonntag, 29.12.2013 - 10:04:19", 410891318 => "Mittwoch, 08.01.2014 - 17:28:38", 412528640 => "Montag, 27.01.2014 - 16:17:20", 413028709 => "Sonntag, 02.02.2014 - 11:11:49", 414241970 => "Sonntag, 16.02.2014 - 12:12:50", 433494560 => "Samstag, 27.09.2014 - 09:09:20" ); foreach my $key ( keys %date_pairs ) { print "="x130; my $timestamp = $key; my ($year,$month,$day, $hour,$min,$sec, $doy,$dow,$dst) = Localtime($timestamp); print "\nOriginal Vars:\nTimestamp is: $timestamp\nYear: $year, Mo +nth: $month, Day: $day, Hour: $hour, Minutes: $min, Seconds: $sec, Da +y of Year: $doy, Day of Week: $dow, Daylight saving: $dst \n","_"x130 +,"\n"; $year += 31; $dow = Day_of_Week($year,$month,$day); my $lang = 3; # this is for German language my $dow_name = Day_of_Week_to_Text($dow,$lang); my $calculated_date = sprintf "%s, %02s.%02s.%d - %02s:%02s:%02s", + $dow_name, $day, $month, $year, $hour, $min, $sec; print "Transformed Vars:\nYear: $year, Month: $month, Day: $day, H +our: $hour, Minutes: $min, Seconds: $sec, Day of Year: $doy, Day of W +eek: $dow, Daylight saving: $dst \nCalculated Date:\t$calculated_date +\nExpected Date:\t\t$date_pairs{$key}\n"; } print "="x130;

Replies are listed 'Best First'.
Re: Date::Calc and and daylight savings time
by Anonymous Monk on Jan 01, 2015 at 11:11 UTC
    Try using Gmtime not Localtime ... at least on my machine it goes from 05:13:27 to 12:13:27, much closer to 13:13:27
    while( my( $epoch, $wanted ) = each %date_pairs ){ use Time::Piece qw/ localtime gmtime /; use Date::Language; my $tp = gmtime( $epoch ); $tp = $tp->add_years( 31 ); my $lang = Date::Language->new('German'); my $got = $lang->strftime("%A, %d.%m.%Y - %H:%M:%S", $tp ); print "$got\n$wanted\n\n"; }

      Thank you! That's an interesting approach. I never used this module: Time::Piece

      Only Problem: on my Macintosh with 5.18.2 (Built in for MacOS 10.10.1) I get totally wrong results:

      Sonntag, 02.02.2014 - 10:11:49 Sonntag, 02.02.2014 - 11:11:49 Montag, 27.01.2014 - 15:17:20 Montag, 27.01.2014 - 16:17:20 Samstag, 27.09.2014 - 07:09:20 Samstag, 27.09.2014 - 09:09:20 Sonntag, 16.02.2014 - 11:12:50 Sonntag, 16.02.2014 - 12:12:50 Mittwoch, 08.01.2014 - 16:28:38 Mittwoch, 08.01.2014 - 17:28:38 Sonntag, 29.12.2013 - 09:04:19 Sonntag, 29.12.2013 - 10:04:19 Sonntag, 26.05.2013 - 12:13:27 Sonntag, 26.05.2013 - 13:13:27

        It seems two things that you're missing - you need to adjust for the Germany/Berlin timezone (GMT+1), and you also (still) need to figure out when DST is active (which accounts for the two hours difference in September).

        I think DateTime comes with the Olson database embedded, but maybe there are less heavyweight approaches to correcting the timestamp for DST.

Re: Date::Calc and and daylight savings time
by pme (Monsignor) on Jan 01, 2015 at 14:06 UTC
    Hi marek,

    This piece of code seems to work fine on my linux box, except for item: 391263207 => "Sonntag, 26.05.2013 - 13:13:27". Could you run it on more data?

    #!/usr/bin/perl use warnings; use strict; use Date::Calc qw(Day_of_Week Day_of_Week_to_Text); use Time::Local; my %date_pairs = ( 391263207 => "Sonntag, 26.05.2013 - 13:13:27", 410000659 => "Sonntag, 29.12.2013 - 10:04:19", 410891318 => "Mittwoch, 08.01.2014 - 17:28:38", 412528640 => "Montag, 27.01.2014 - 16:17:20", 413028709 => "Sonntag, 02.02.2014 - 11:11:49", 414241970 => "Sonntag, 16.02.2014 - 12:12:50", 433494560 => "Samstag, 27.09.2014 - 09:09:20" ); $ENV{TZ} = 'Europe/Berlin'; # sec,min,hours,day,month,year my $epoch = timegm(0, 0, 0, 1, 0, 70); my $macep = timegm(0, 0, 0, 1, 0, 101); print "$epoch -- $macep\n"; foreach my $key ( sort keys %date_pairs ) { # 0 1 2 3 4 5 6 7 8 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localti +me($key+$macep); $mon++; $year += 1900; my $dstr = Day_of_Week_to_Text(Day_of_Week($year, $mon, $mday), 3) +; my $datestr = sprintf("%-8s %02d.%02d.%02d %02d:%02d:%02d %d", $ds +tr, $mday, $mon, $year, $hour, $min, $sec, $isdst); print "$key - $date_pairs{$key} -- $datestr\n"; }
    Output:
    0 -- 978307200 391263207 - Sonntag, 26.05.2013 - 13:13:27 -- Sonntag 26.05.2013 14: +13:27 1 410000659 - Sonntag, 29.12.2013 - 10:04:19 -- Sonntag 29.12.2013 10: +04:19 0 410891318 - Mittwoch, 08.01.2014 - 17:28:38 -- Mittwoch 08.01.2014 17: +28:38 0 412528640 - Montag, 27.01.2014 - 16:17:20 -- Montag 27.01.2014 16: +17:20 0 413028709 - Sonntag, 02.02.2014 - 11:11:49 -- Sonntag 02.02.2014 11: +11:49 0 414241970 - Sonntag, 16.02.2014 - 12:12:50 -- Sonntag 16.02.2014 12: +12:50 0 433494560 - Samstag, 27.09.2014 - 09:09:20 -- Samstag 27.09.2014 09: +09:20 1
    Regards

      Great! The New Year 2015 starts really fantastic! :-)
      I am so grateful for your answer. Strange, that apparently we have to mix up two Modules (Date::Calc and Time::Local) to get it right.

      I have to read the manual of Time::Local to fully understand your answer.
      Funny that the first timestamp (391265355) gets the wrong daylight savings time.
      One moment: May is far into the daylight saving time == 1 ... So it is right. Probably my expected date is wrong hmmmm

      I will try to find an answer on myself.

      Thank you again :-)

      marek

Re: Date::Calc and and daylight savings time
by Anonymous Monk on Jan 01, 2015 at 15:31 UTC

    Unfortunately Date::Calc does not install cleanly for me. But I have the same problem with both Perl's built-in time functionality (specifically POSIX::strftime()) and the DateTime module. Both claim that time stamp 391263207 corresponds to 'Sonntag, 26.05.2013 - 14:13:27', using time zones 'CET-1CDT', 'Europe/Berlin', and 'Europe/Busingen', and locale 'de_DE'. I calculate the GMT date for this time stamp as 'Sonntag, 26.05.2013 - 12:13:27'.

    So this means Perl thinks Summer time (+2 offset from GMT) is in effect at time stamp 391263207, while your SMS log thinks it was not. I do not live in Germany, so I do not know for sure which is correct. But the end of May seems to me awfully late in the year for Winter time. Or awfully early. Maybe you should step back from the programming problem and try to figure out whether Summer or Winter time was in effect at that time. If it's Summer, then Perl is right.