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

Greetings! I am running in to invalid date time problem and require your advice/help. I am reading a file which has date and time in PST (America/Los_Angeles). I am converting it to UTC I encounter an error when run the time 03/113/2016 00:02:00. 13th March 2016 2Am is daylight saving.

use DateTime; $occuranceTime = "00:02:00"; $occuranceDate = "03/13/2016"; my $recordYear = substr ($occuranceDate, 6,4); my $recordMonth = substr ($occuranceDate, 0,2); my $recordDate = substr ($occuranceDate, 3,2); my $recordSec = substr ($occuranceTime, 0,2); my $recordHour = substr ($occuranceTime, 3,2); my $recordMin = substr ($occuranceTime, 6,2); my $recordOnPST =DateTime->new( year => $recordYear, month => $rec +ordMonth, day => $recordDate, hour => $recordHour, minute => $recordMin +, second => $recordSec, time_zone => 'America/Los_Angeles'); #my $recordOnPST =DateTime->new( year => $recordYear, month => +$recordMonth, day => $recordDate, # hour => $recordHour, minute => $recordMi +n, second => $recordSec, time_zone => 'floating'); my $recordOnUTC = $recordOnPST ->set_time_zone('UTC'); print "$recordOnPST \n"; print "$recordOnUTC \n";

I did try to use time zone as floating (which is UTC) but had no success (I mean I need to time first in PST before I convert to UTC) Thank in advance for all your assistance

Replies are listed 'Best First'.
Re: DateTime Invalid local time for date in time zone (updated)
by haukex (Archbishop) on Jul 10, 2018 at 18:07 UTC

    It does seem that, at least according to DateTime, the time 13th March 2016 2 a.m. does not exist:

    I am converting it to UTC I encounter an error when run the time 03/113/2016 00:02:00. 13th March 2016 2Am is daylight saving.

    Do you know how this time was recorded? Do you have any other times from 2:00am through 2:59am? Because if you do, I think you might have a bigger problem. I would strongly recommend looking at fixing the source of the data first.

    I'm also confused: according to your substr, is your time format really SS:MM:HH SS:HH:MM?? In any case, I'd recommend using a "proper" parser like DateTime::Format::Strptime.

    But if it's only 2016-03-13T02:00:00 that is incorrect, then I'd suggest "patching" this manually. Parse the date in the "floating" time zone, "fix" the time*, and then set the time zone. (If you have lots of incorrect date/time values like this, this might cumbersome, hence my above suggestion to fix it at the source instead.)

    use warnings; use strict; use DateTime; use DateTime::Format::Strptime; my $str = "03/13/2016 02:00:00"; my $strp = DateTime::Format::Strptime->new( pattern => '%m/%d/%Y %H:%M:%S', time_zone=>'floating', on_error=>'croak'); my $dt = $strp->parse_datetime($str); if ($dt->year==2016 && $dt->month==3 && $dt->day==13 && $dt->hour==2) { # any minute and second $dt->add(hours=>1); } $dt->set_time_zone('America/Los_Angeles'); print $dt->strftime('%Y-%m-%d %H:%M:%S %Z'),"\n"; __END__ 2016-03-13 03:00:00 PDT

    * Update: However, If you have records, for example, at 2:15am and 3:15am, the above code will make them look like the same time! That's why I said above that this only makes sense if you only have 02:00:00 as a time to fix. For example, I imagine it's possible the software that wrote these records makes the DST jump incorrectly from 02:00:59 to 03:01:00, which means there shouldn't be any records between those times.

      You are correct. I realized this is a data error 03/13/2016 2 am and should never exist (preciously at 01:59:59 the time should have jumped to 03:00:00).

        Alternatively, use the correct time zone (-0800 instead of America/Los_Angeles).

Re: DateTime Invalid local time for date in time zone
by mr_ron (Deacon) on Jul 11, 2018 at 00:59 UTC

    It looks from the OP like you are parsing time in format seconds:hours:minutes which seems unfamiliar. Are you sure the file has 2AM and not two minutes past midnight? The documentation for DateTime mentions the 2AM problem in an "Invalid Local Times" section.

    Ron
      Agreed but unfortunately the source file is in the format of seconds:hours:minutes :(

        Thank you for getting back on my question.

        So, as documented in the "Invalid Local Times" and "Error Handling" sections, DateTime was throwing an exception by "die"ing with a string explaining the problem. haukex solution would do something very similar on $dt->set_time_zone('America/Los_Angeles'); if it didn't add an hour before setting the time zone. If it is possible that there may be other invalid timestamps based on DST then you can also catch the exception, try to verify that the problem is DST and handle the error accordingly. I am presenting, below, an exception handling solution based on your OP but you might want to similarly adjust the haukex solution.

        #!/usr/bin/env perl use strict; use warnings; use DateTime; use Try::Tiny; my $occuranceTime = "00:02:00"; my $occuranceDate = "03/13/2016"; my ($recordSec, $recordHour, $recordMin) = split ':', $occuranceTime; my ($recordMonth, $recordDate, $recordYear) = split '/', $occuranceDat +e; my $recordOnPST = try { DateTime->new( year => $recordYear, month => $recordMonth, day => $recordDate +, hour => $recordHour, minute => $recordMin, second => $recordSe +c, time_zone => 'America/Los_Angeles' ); } catch { if ( /^Invalid local time for date in time zone/ and $recordMonth == 3 and $recordHour == 2 ) { warn "Looks like invalid DST timestamp\n"; return DateTime->new( year => $recordYear, month => $recordMonth, day => $record +Date, hour => $recordHour +1, minute => $recordMin, second => $r +ecordSec, time_zone => 'America/Los_Angeles' ); } else { die $_; # try to rethrow other exception } return undef; # in case you don't want to return adjusted time }; if ($recordOnPST) { my $recordOnUTC = $recordOnPST -> clone -> set_time_zone('UTC'); print "$recordOnPST \n"; print "$recordOnUTC \n"; }
        Ron
Re: DateTime Invalid local time for date in time zone
by ikegami (Patriarch) on Jul 11, 2018 at 08:08 UTC
      Thank you for the tip. I will check it out