in reply to How to compare date/times in different timezones?

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

Replies are listed 'Best First'.
Re^2: How to compare date/times in different timezones?
by Jim (Curate) on Aug 28, 2011 at 19:43 UTC
      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.

        Excellent!

        The rule of thumb for most date and time calculations is to normalize both moments to UTC first, then perform the math. But in this case, it really only makes sense to compare dates from the perspective of a specific local time. It's easy to imagine a practical application for wanting to know if two moments at two different places in the world occurred on the same date reckoned from Sydney, Australia. It's not as easy to imagine a practical application for wanting to know if two moments occurred on the same date reckoned from UTC, which is abstract. Who would care?

        Consider this very light refactoring:

        #!perl use strict; use warnings; use DateTime; use DateTime::Format::DateParse; @ARGV == 2 or die "Usage: perl $0 <timestamp 1> <timestamp 2>\n"; my $ts1 = shift; my $ts2 = shift; my $tz = 'Australia/Sydney'; my $dt1 = DateTime::Format::DateParse->parse_datetime($ts1) ->set_time_zone($tz); my $dt2 = DateTime::Format::DateParse->parse_datetime($ts2) ->set_time_zone($tz); my $diff = $dt1->delta_days($dt2)->delta_days(); print "$dt1 delta $dt2 is $diff days\n"; exit 0;
Re^2: How to compare date/times in different timezones?
by philled (Novice) on Aug 28, 2011 at 12:16 UTC
    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?