Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

setting TZ causes Date::Manip to report incorrect time

by meonkeys (Chaplain)
on Sep 09, 2003 at 00:17 UTC ( [id://289914]=perlquestion: print w/replies, xml ) Need Help??

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

If I set the TZ environment variable to my timezone (currently PST), Date::Manip::ParseDate seems to incorrectly parse the string 'today' as GMT.

For instance:

$ perl -MDate::Manip -e 'print UnixDate(ParseDate("today"),"%C"),"\n"' +; date +"%c" Mon Sep 8 17:15:03 -0700 2003 Mon 08 Sep 2003 05:15:03 PM PDT # okay so far, the output matches that of UNIX 'date' $ TZ=PDT perl -MDate::Manip -e 'print UnixDate(ParseDate("today"),"%C" +),"\n"'; date +"%c" Tue Sep 9 00:15:04 -0700 2003 Mon 08 Sep 2003 05:15:04 PM PDT # why does Date::Manip give me GMT and report -0700???

Does anyone know what's going on with Date::Manip?



---
"A Jedi uses the Force for knowledge and defense, never for attack."

Replies are listed 'Best First'.
Re: setting TZ causes Date::Manip to report incorrect time
by BigLug (Chaplain) on Sep 09, 2003 at 06:24 UTC
    As you have discovered, there are various problems with Time Zones and Date::Manip. If I were you, I'd take a look at the DateTime project. Using DateTime means you can get rid of that clutter of date modules that was previously needed to work with dates in Perl. The DateTime modules know all about Time Zones, including when local governing bodies changed their moves in and out of daylight savings. DateTime also knows about leap seconds and so carries accuracy over long periods very well.

    There are a library of DateTime modules now available that can help you with anything related to dates and times, including working with httpd logs, with databases and even with using your own date formats. DateTime offers both strftime and strptime, so you're never limited by existing format modules.

    DateTime also does a good job of durations and never assumes there's 24 * 60 * 60 seconds in a day. A fault of most (if not all) previously existing date and time modules.

    However, like Date::Manip, DateTime needs to find your local time zone from somewhere if you want to talk about 'local' dates and times. But if your machine doesn't already have the information DateTime needs, there's no need to worry. If you know where you are (and most of us do!) you should be setting it anyways.

    If timezones don't matter, then there's always the 'floating' timezone. This zone just 'floats' your datetime until you allocate a time zone to it. Huh? Well, if you make a datetime for 5pm on Sept 9, 2003 but don't specify a timezone then it's 'floating'. One you $dt->set_timezone('SomeZone') then it becomes 5pm on Sept 9, 2003 in SomeZone. It doesn't change the time, just the zone its in. Now if you were to change from SomeZone to UTC (similar to GMT), it becomes some other time, depending on the offset of SomeZone to UTC.

    All in all, the DateTime modules solve pretty much any problem to do with dates and times in perl. If you have a problem that it doesn't solve then you're in luck: the development group is very active and will listen to anything you need.

    At this point I should point out that I am one of the lowly developers in the project, so I have a certain bias. Despite this, and thinking as objectivly as I can, I still think DateTime is the best solution for most date and time problems in perl.

    You can contact the mailing list at datetime@perl.org, and can download the modules from CPAN.

      I appreciate the helpful reply with information about the DateTime project. However, it doesn't seem to answer questions like:

      • What are valid values for the TZ environment variable?
      • Why did Date::Manip behave as I described?

      I feel like you ignored my original post. :(

      the DateTime modules solve pretty much any problem to do with dates and times in perl

      Good to know. What about parsing the date 'today'? How is that affected by time zones? Which of the plethora of DateTime modules should I use to parse 'today' and format it as 'Tue Sep 9 12:12:12 PDT 2003'?

      ---
      "A Jedi uses the Force for knowledge and defense, never for attack."

        Valid values for the TZ variable when using DateTime are anything that matches a valid Olson time zone name, like "America/Chicago". When using Date::Manip they're whatever the Date::Manip docs say are valid. See the "TIMEZONES" section of the docs.

        Why did Date::Manip behave as you described? Presumably there's a bug in Date::Manip, or your expectations are wrong and Date::Manip can't do what you want.

        How often do you need to parse things like "today" and "two days after tomorrow" anyway? With DateTime, for just getting "today" you'd do DateTime->today(). To format it as above you'd do $dt->strftime('%a %b %e %H:%M:%S %Z %Y'). However, you're strongly discouraged from using short time zone names like "PDT" for anything but display, because they are not unique.

        I appreciate the helpful reply with information about the DateTime project. However, it doesn't seem to answer questions like:

        * What are valid values for the TZ environment variable?
        * Why did Date::Manip behave as I described?

        I feel like you ignored my original post. :(

        Sorry you feel that way, however I was trying to answer your question by offering a solution, rather than just straight answering your question.

        Your question was "Does anyone know what's going on with Date::Manip?" The answer to which is 'no', see below. As to the questions in your reply:

        * What are valid values for the TZ environment variable?
        This is not a perl question but one which should be addressed to your operating system. However if you're looking for valid values for Date::Manip, I'd check their POD or even their source. Remember however that if you specify PDT or -0700 (assuming Date::Manip accepts these values) then you will not get any daylight savings information and the number of hours between June 30 and Dec 31 will be a multiple of 24.

        * Why did Date::Manip behave as I described?
        It looks like there's either a bug in D:M or it's a feature you're not using properly. I'm guessing that it's a bug because I can't make sense of it as a feature.

Re: setting TZ causes Date::Manip to report incorrect time
by Thelonius (Priest) on Sep 09, 2003 at 01:28 UTC
    You need to say TZ=PST8PDT. PDT by itself is not the name of a timezone.

      Uggggh. According to the POD from Date::Manip, PDT and PST are both valid values for TZ! Plus, there's no mention of 'PST8PDT', something I never would've guessed to try. :(

      The following timezone names are currently understood (and can be used in parsing dates). These are zones defined in RFC 822. Universal: GMT, UT US zones : EST, EDT, CST, CDT, MST, MDT, PST, PDT Military : A to Z (except J) Other : +HHMM or -HHMM ISO 8601 : +HH:MM, +HH, -HH:MM, -HH

      How did you know that it needs to be PST8PDT for the Pacific time zone? Could you point me to some manpages, books, or hyperlinks?

      The only box-specific timezone information I can find on my machine is ZONE="America/Los_Angeles" in /etc/sysconfig/clock, but I don't know if this is Redhat-specific. Could you point me to another file where the default timezone is garnered if TZ isn't set?

      I did find a page which gives some specific examples on what to set TZ to. Anyone who finds more info, please share!

      Update:
      Found this mention of PST8PDT in the docs:

      The timezone may be in the STD#DST format (in which case both abbreviations must be in the table above) or any of the formats described above.
      However, this also implies that 'PDT' is a valid value for the TZ environment variable, but it doesn't seem to work correctly (see original question).

      ---
      "A Jedi uses the Force for knowledge and defense, never for attack."
        Try /etc/TIMEZONE.
Re: setting TZ causes Date::Manip to report incorrect time
by wufnik (Friar) on Sep 09, 2003 at 09:07 UTC
    initially, i also had time zone problems using Date::Manip

    however, for myself, the following, at the head of a script using Date::Manip, solves the problem:
    Date_Init("TZ=GMT", "WorkDayBeg=$wdb", "WorkDayEnd=$wde");
    with s/GMT/yourtimezone, ($wdb, $wde) = ("08:00", "17:00").

    as for the list of timezones, i found them in the Date::Manip perldoc too, but yes, no mention of "PST8PDT". Thelonius gets his info from the source itself, where you will find PST8PDT, MST7MDT, CST6CDT etc. i believe these are shorthands for 'US/Pacific', 'US/Mountain', which are in the documentation for Date::Manip.

    given that Date::Manip is as useful as it is, esp. for business day calcs, it is a pity the docs are not a little more expansive on the subject.

    Does this mean that Date::Manip has problems with timezones, as BigLug suggests? i think the docs, rather than the code, are the problem. it would be interesting to see a proper comparison of DateTime functionality with Date::Manip; i would be surprised if Date::Manip came off worst:

    Date::Manip can alter the number of seconds in the day via "WorkDayBeg" and "WorkDayEnd" in Date_init() (see above), so it, at least, does not suffer from making the assumption that there are 24*60*60 seconds in a day.

    In addition formats parsed and output by Date::Manip are really extensive. It has been the only date module i have ever needed, and "use Date::Manip" is not exessively cluttery.

    however, i have to say, i found it took me a while to get to grips with the intricacies of this important but labour-intensive module. i see no tutorials in PM involving Date::Manip; has the time come for one?

    here is hoping...

    wufnik

    ...in the world of the mules there are no rules

      Does this mean that Date::Manip has problems with timezones, as BigLug suggests? i think the docs, rather than the code, are the problem. it would be interesting to see a proper comparison of DateTime functionality with Date::Manip; i would be surprised if Date::Manip came off worst:

      Well, as someone who's used every datetime module under the sun, and then got sick of them and wrote DateTime, I wouldn't be surprised if Date::Manip came off worse, because I know that it will.

      Specifically, try doing this with Date::Manip:

      my $dt1 = DateTime->new( year => 2003, month => 5, day => 2, hour => 7, minute => 53, time_zone => 'Asia/Tokyo' ); my $dt2 = DateTime->new( year => 2003, month => 5, day => 2, hour => 5, minute => 53, time_zone => 'Asia/Calcutta' ); if ( $dt1 > $dt2 ) { ... } else { ... } $dt1->set_time_zone( 'Asia/Calcutta' ); print $dt1->datetime, "\n"; print $dt2->datetime, "\n";

      If that sort of thing is even possible with Date::Manip, it'd be much, much, much more code.

      Date::Manip can alter the number of seconds in the day via "WorkDayBeg" and "WorkDayEnd" in Date_init() (see above), so it, at least, does not suffer from making the assumption that there are 24*60*60 seconds in a day.

      What BigLug was referring to when he mentioned this was the existence of leap seconds, not the idea of "business hours". Some days last longer than 24*60*60 seconds on the clock, according to the UTC system. However, this only happens to one day every couple years or so. You can't simply change the length of the day and leave it at that. That would be quite broken.

        So I'll take your challenge and say .. I think its working, if you dig into how its intended to work. Using your exact example dataset, I reformatted it for Date::Manip. Some may have other opinions on how to set the date, but this is compact and for me easy to follow:
        use strict; use warnings; use Date::Manip; my $dt1 = Date::Manip::Date->new(); my $dt2 = Date::Manip::Date->new(); $dt1->config("setdate","zone,Asia/Tokyo"); $dt2->config("setdate","zone,Asia/Calcutta"); $dt1->parse("20030502T07:53"); $dt2->parse("20030502T05:53"); if ( $dt1->cmp($dt2) ) { print "dt1 ftw!\n"; } else { print "dt2 ftw!\n"; } print $dt1->printf("dt1 %c %Z\n"); $dt1->convert("Asia/Calcutta"); print $dt1->printf("dt1 %c %Z\n"); print $dt2->printf("dt2 %c %Z\n");
        Output is:
        $ perl ./testdate dt1 ftw! dt1 Fri May 2 07:53:00 2003 JST dt1 Fri May 2 04:23:00 2003 IST dt2 Fri May 2 05:53:00 2003 IST
        autarch, those seem eminently reasonable points.

        the two modules evidently occupy similar niches. while your example above is persuasive, it would be surprising if Date::Manip did not have strengths it would be too tedious to mention.

        i think what would be very helpful to the general monk population is a pithy comparison table, outlining the various points that would be useful, and whether datetime or date::manip holds the higher ground. BigLug suggested as much.

        what better way to convince us of your assertion:

        i know that it will. ?

        best wishes, ...wufnik

        -- in the world of the mules there are no rules --
      it would be interesting to see a proper comparison of DateTime functionality with Date::Manip; i would be surprised if Date::Manip came off worst
      OK, lets find a framework for the comparison. I'm very much interested in this.

      Here's some suggestions for comparison of results:

      • Acurateness of result
      • Brevity of code
      • Understandability of code
      • Reusability of data
      I think the next place to go from here is to make a list of tasks that each module is to perform. Anyone reading this who is an advocate of Date::Manip? I'd hate to create a list of tests only to be told DateTime wins simply because all the tests were written by a DateTime developer.

      Please, anyone, tell me the tasks you use Date::Manip for. From the top post in this thread I assume we want the current time and date in the local time zone, formatted in the locally preferred format.

      use Date::Manip; $ENV{TZ} = 'EST'; print UnixDate(ParseDate("today"),"%c"); #use Date::Manip;$ENV{TZ}=;print UnixDate(ParseDate(),) use DateTime; print DateTime->now(time_zone=>'Australia/Melbourne')->strftime("%c"); #use DateTime;print DateTime->now(time_zone=>)->strftime()
      TestDate::ManipDateTimeCommend
      Acurateness of results01As evidenced by the post, Date::Manip does not work.
      Brevity of Code10.9 
      Understandability of code0.60.8Both have their weaknesses here. They both use the symbol %c, which is not too clear. However in DateTime, we see the command for the %c right next to it, rather than in D:M where the command is back at the start of the line. I also took points off D:M for the use of %ENV. Looking at this snippet in a large script, it wouldn't be too obvious that the two commands were related in any way.
      1.62.7

      Scoring:
      Acurateness of results: 1 if accurate, 0 if inaccurate
      Brevity of Code: 1 for the shorter code, once data has been removed. Then the longer gets shorter/longer.
      Understandability of code: Value judgement.

      Of course, I'm open to any criticism, additions and corrections to my comparison. I'd really like to create a fair comparison of various common tasks. Send me your code and your comparisons. Or just send me your test-in-english and I'll code them both.

        Well, if an algorithm had 50 lines of code to add 2 numbers together, and another had 25 lines, you may argue that the shorter is better.. but define better. Does the 50 line one take in special occurrences so that it does things faster? Is it clearer to read? Don't create statistics for thse types of subjective things unless they have a real concrete measurement, like in seconds vs data for performance. It just mucks up the works.

        If something is better in one way that can't be proven by numbers, just say so. "CGI.pm - it works, but he innards look like shit, but it's a proven standard" Same with Date::Manip - "It's a standard module, but it works like shit when you throw certain data at it.. though DateTime works and is new."

        People will make their own judgements depending on their needs. Like cricket. It's a really ugly script, but you know, it works. It works well and is very configurable, but it's easy to miscnfigure and berak. So will you use it over something that is unbreakable but limited? That's up to you. :)

        Lies, bigger lies, and then there are statistics, to paraphase :)
        --
        Play that funky music white boy..

Re: setting TZ causes Date::Manip to report incorrect time
by bobn (Chaplain) on Sep 09, 2003 at 01:01 UTC

    I get the same thing.

    From perldoc Date::Manip

           Date::Manip must be able to determine the timezone the user is in.  It
           does this by looking in the following places:
    
              $Date::Manip::TZ (set with Date_Init or in Manip.pm)
              $ENV{TZ}
              the unix `date` command (if available)
              $main::TZ
              /etc/TIMEZONE
              /etc/timezone
    
           At least one of these should contain a timezone in one of the supported
           forms.  If none do by default, the TZ variable must be set with
           Date_Init.
    
    My guess is that, like on my system, TZ isn't set. what isn't clear is why the unix date command isn't getting used - like yours, mine shows the local timezone.

    The only thing I've found on my system is /etc/adjtime:

    0.001227 1061666277 0.000000
    1061666277
    UTC
    

    --Bob Niederman, http://bob-n.com

    All code given here is UNTESTED unless otherwise stated.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://289914]
Approved by Thelonius
Front-paged by hossman
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2024-04-25 16:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found