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

I have two date/time strings that I need to compare to see if they are the same date or not. One is "Fri, 26 Aug 2011 14:34:55 GMT" and the other is "Sat, 27 Aug 2011 07:03:02 +1000".

I guess it's a two-step process:
1) Convert them both to the same timezone, and then
2) Compare the date component of the date/time to see if they're the same date.

I've been searching around and am now totally bewildered and baffled by the various date & time modules available. I have tried a few and can't work out how to do this. I'm not a perl programmer, I'm an occasional dabbler, but I would have thought it would be simple. Can anyone provide a straightforward way of doing this?

  • Comment on How to compare date/times in different timezones?

Replies are listed 'Best First'.
Re: How to compare date/times in different timezones?
by CountZero (Bishop) on Aug 27, 2011 at 09:59 UTC
    Convert all datetimes to the universal UTC timezone and then compare. No need to reinvent the wheel!

    use Modern::Perl; use DateTime; use DateTime::Format::Flexible; my $first_dt = DateTime::Format::Flexible->parse_datetime( 'Fri, 26 Au +g 2011 14:34:55 GMT'); my $second_dt = DateTime::Format::Flexible->parse_datetime( 'Sat, 27 A +ug 2011 07:03:02 +1000'); my $first_dt_utc = $first_dt->set_time_zone('UTC'); my $second_dt_utc = $second_dt->set_time_zone('UTC'); say $first_dt_utc->delta_days( $second_dt_utc )->delta_days, ' days of + difference';
    It returns "0 days of difference".

    The delta_days method takes into account only the date part of the DateTime object and returns a DateTime::Duration object and the delta_days method (of the DateTime::Duration-object, nothing to do with the delta_days method of the DateTime-object! Speaking of confusion here) converts that into a number of days.

    Or without any intermediary steps or variables:

    use Modern::Perl; use DateTime; use DateTime::Format::Flexible; say DateTime::Format::Flexible->parse_datetime( 'Fri, 26 Aug 2011 14:3 +4:55 GMT')->set_time_zone('UTC')->delta_days(DateTime::Format::Flexib +le->parse_datetime( 'Sat, 27 Aug 2011 07:03:02 +1000')->set_time_zone +('UTC'))->delta_days, ' days of difference';
    Update: Changed the ->days method to the ->delta_days method as per Jim's excellent suggestion.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        Just wanted to say thanks to everyone for their help on this. I think I've finally got there now. For the record the code I'm using is as follows. I'm converting the datetime into Australia/Sydney timezone before doing the comparison.
        use DateTime::Format::DateParse; my $p1 = shift; my $p2 = shift; my $first_dt = DateTime::Format::DateParse->parse_datetime("$p1"); my $second_dt = DateTime::Format::DateParse->parse_datetime("$p2"); my $first_dt_syd = $first_dt->set_time_zone('Australia/Sydney'); my $second_dt_syd = $second_dt->set_time_zone('Australia/Sydney'); my $diff = $first_dt_syd->delta_days( $second_dt_syd )->delta_days;

        Thanks again.

      Thanks for this. It looked like an excellent and simple solution. Unfortunately for me, I'm running CentOS 5.5 and there doesn't seem to be an RPM for perl-DateTime-Format-Flexible. While it's possible to get hold of a noarch version, that then generates dependency errors with perl(:MODULE_COMPAT_5.12.3) yadda yadda yadda...

      Is there a similar solution that doesn't use DateTime::Format::Flexible?

        Is there a similar solution that doesn't use DateTime::Format::Flexible?

        Use DateTime::Format::Natural instead.

        According to the DateTime project wiki, it's what you're supposed to use instead of DateTime::Format::Flexible in any case. (See Confusing Modules.)

        ikegami already demonstrated using yet another DateTime module, DateTime::Format::DateParse, in his reply to your original post.

        Here's CountZero's script refactored using DateTime::Format::Natural.

        #!perl use strict; use warnings; use DateTime; use DateTime::Format::Natural; my $parser = DateTime::Format::Natural->new(); my $first_timestamp = 'Mon, 27 Aug 2007 14:34:55 GMT'; my $second_timestamp = 'Sat, 27 Aug 2011 07:03:02 +1000'; $first_timestamp = $parser->extract_datetime($first_timestamp); $second_timestamp = $parser->extract_datetime($second_timestamp); my $first_dt = $parser->parse_datetime($first_timestamp); my $second_dt = $parser->parse_datetime($second_timestamp); print $first_dt->delta_days($second_dt)->days(), " days difference\n"; exit 0;

        This prints "5 days difference". To me, this isn't what you're after. Is it? (N.B. I used a different first timestamp than the one you presented.)

        Frankly, your problem confounds me. When it's 12:30 a.m. on January 1 in New York City (U.S. Eastern Time), it's 11:30 p.m. on December 31 in Chicago (U.S. Central Time). By definition, this moment in time occurs on two different dates in those two time zones. In fact, they're different days of the week, different dates of the month, different months and different years.

        UPDATE: Epic fail. DateTime::Format::Natural doesn't parse the timestamps correctly at all. Psshh!

        DateTime::Format::DateParse is better.

        #!perl use strict; use warnings; use feature qw( say ); use DateTime; use DateTime::Format::DateParse; use DateTime::Format::Strptime; my $first_timestamp = 'Fri, 27 Jul 2007 14:34:55 GMT'; my $second_timestamp = 'Wed, 27 Jul 2011 07:03:02 +1000'; say $first_timestamp; say $second_timestamp; my $first_dt = DateTime::Format::DateParse->parse_datetime($first_timestamp); my $second_dt = DateTime::Format::DateParse->parse_datetime($second_timestamp); $first_dt->set_time_zone('UTC'); $second_dt->set_time_zone('UTC'); my $strp = DateTime::Format::Strptime->new(pattern => '%F %T %z'); say $strp->format_datetime($first_dt); say $strp->format_datetime($second_dt); say $first_dt->delta_days($second_dt)->delta_days(), ' days difference'; exit 0;

        This prints…

        Fri, 27 Jul 2007 14:34:55 GMT
        Wed, 27 Jul 2011 07:03:02 +1000
        2007-07-27 14:34:55 +0000
        2011-07-26 21:03:02 +0000
        1460 days difference
        

        Sorry. You wanted clarification, but you got more confusion.

        cpan DateTime::Format::Flexible doesn't work for you?

Re: How to compare date/times in different timezones?
by ikegami (Patriarch) on Aug 27, 2011 at 06:11 UTC

    If two timestamps share a date from which time zone's perspective: any time zone or a specific time zone?

    The former requires checking if the time stamps are within 24 hours of each other.

    The latter requires comparing the dates of the time stamps after converting the time stamps to the specific time zone.

    use strict; use warnings; use DateTime::Format::DateParse qw( ); sub same_date_anywhere { my ($dt1, $dt2) = @_; ($dt1, $dt2) = ($dt2, $dt1) if $dt1 < $dt2; $dt1 = $dt1->clone(); $dt1->subtract( hours => 24 ); return $dt1 < $dt2; } sub same_date_somewhere { my ($dt1, $dt2, $tz) = @_; for my $dt ($dt1, $dt2) { ( $dt = $dt->clone() ) ->set_time_zone($tz) ->truncate( to => 'days' ); } return $dt1 == $dt2; } my $dt1 = DateTime::Format::DateParse->parse_datetime("Fri, 26 Aug 201 +1 14:34:55 GMT"); my $dt2 = DateTime::Format::DateParse->parse_datetime("Sat, 27 Aug 201 +1 07:03:02 +1000"); say(same_date_anyhere($dt1, $dt2) ?1:0); say(same_date_somewhere($dt1, $dt2, $dt1->time_zone) ?1:0); say(same_date_somewhere($dt1, $dt2, $dt2->time_zone) ?1:0); say(same_date_somewhere($dt1, $dt2, "America/New_York") ?1:0); say(same_date_somewhere($dt1, $dt2, "UTC") ?1:0);

    Untested.

      The former requires checking if the time stamps are within 24 hours of each other.
      Baker Island uses timezone UTC-12:00, while Christmas Island uses UTC+14:00. That's a 26 hour window.
Re: How to compare date/times in different timezones?
by Anonymous Monk on Aug 27, 2011 at 06:08 UTC
Re: How to compare date/times in different timezones?
by locked_user sundialsvc4 (Abbot) on Aug 29, 2011 at 00:08 UTC

    Don’t let what is pre-supplied by RPMs in a Linux distribution dissuade you from prowling about in topics here that talk about “installing Perl as a non-root user.”   Soon enough, you will need to learn about this.   (And I would like for you to please “Super Search” this, and to read some posts, before I continue.

    You can install Perl packages such that they are visible to your own local Perl environment even if the packages for your “distro” do not automatically provide them.   You need to learn about how to do this because you will wind up needing to do this, “sooner rather than later ... and in your case, quite possibly right-now.”

    /me nods...   (I say in the best possible way ... with my biggest good-natured smile...) “Well, the training wheels have got to come off sometime.”