6

I wanted to know if there is a way to get the time zone offset for a given date range between two timezones for a given duration.

getTimezoneOffset(startDate,endDate,timezone1,timezone2){
    ...missing magic to go here...
}

should return the time zone offset which is valid for the a given duration. However if the offset changes, it should return the date range for which it's valid.

So I am looking at something like this:

getTimezoneOFfset("march 9 12 am", "march 15 12 am", "UTC", "US/NEW_YORK")

return value something like this

timezoneoffset[0]["range"]=[march 9 12am to march 11 2 am]
timezoneoffset[0]["offset"]=5
timezoneoffset[1]["range"]=[march 9 2 am to march 15 12 am]
timezoneoffset[1]["offset"]=4

I just don't want to calculate timezone offsets for every scheduled item for the given range. Was looking if there is some way to get a direct lookup for offsets if it's going to change.

I am working with PHP, but a solution in any language will be appreciated.

MySQL solution will also work as it will be more optimized to do this in MySQL.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user1192612
  • 61
  • 1
  • 3

3 Answers3

4

Assuming that you have a newer version of php (5.2.0+) the DateTimeZone class is part of the PHP core and will let you use the getOffset() function to make these calculations. It will let you pass in a dateTime object and specify a timezone. If you do this for both your dates you should be able to calculate all of the pieces you're looking to grab. To use an example from php.net:

// Create two timezone objects, one for Taipei (Taiwan) and one for
// Tokyo (Japan)
$dateTimeZoneTaipei = new DateTimeZone("Asia/Taipei");
$dateTimeZoneJapan = new DateTimeZone("Asia/Tokyo");

// Create two DateTime objects that will contain the same Unix timestamp, but
// have different timezones attached to them.
$dateTimeTaipei = new DateTime(mktime([the date in question]), $dateTimeZoneTaipei);
$dateTimeJapan = new DateTime(mktime([the date in question]), $dateTimeZoneJapan);


// Calculate the GMT offset for the date/time contained in the $dateTimeTaipei
// object, but using the timezone rules as defined for Tokyo
// ($dateTimeZoneJapan).
$timeOffset = $dateTimeZoneJapan->getOffset($dateTimeTaipei);

// Should show int(32400) (for dates after Sat Sep 8 01:00:00 1951 JST).
print("Number of seconds Japan is ahead of GMT at the specific time: ");
var_dump($timeOffset);

print("<br />Number of seconds Taipei is ahead of GMT at the specific time: ");
var_dump($dateTimeZoneTaipei->getOffset($dateTimeTaipei));

print("<br />Number of seconds Japan is ahead of Taipei at the specific time: ");
var_dump($dateTimeZoneJapan->getOffset($dateTimeTaipei)
     -$dateTimeZoneTaipei->getOffset($dateTimeTaipei));
Ben D
  • 14,321
  • 3
  • 45
  • 59
  • I know about get offset ..but get offset just gives u the offset for a given time ..the thing is I have a schedule with schedule items schedule for different times during the day .. – user1192612 Feb 06 '12 at 21:31
  • So if I get a request to get schedule items between 10 march 2012 9 pm tom 11 march 9 am the offset is going to vary for tht duration ..I dont wnat to calculate offsets for every time ..And this is just for US ..different countries will have different days when the offset changes ,.. and I am trying to find the offet between two timezones for a set of duration not necessarily UTC ..the problem is I donno if I calculate the offset based on the start Time it will be the same throughout..I think PHP get offset ggives u the offset for a given time ..I hope I made myself clear – user1192612 Feb 06 '12 at 21:39
  • Bottomline is I have to assume the offset may vary during a day say march 11 12 am to mrach 11 12 pm (offset varies at 2 am )..I am trying to cover this corner case – user1192612 Feb 06 '12 at 21:43
  • getOffset will give you an offset for a specified time only, but what's so bad about calculating it each time? You specify the start datetime and the end datetime... figure out what the offset is for start time and the offset for end time and if it's different take the difference into account... it shouldn't be that hard to write the function `getTimezoneOffset(startDate,endDate,timezone1,timezone2)` based on `getOffset`. – Ben D Feb 06 '12 at 22:08
  • U dont know when the offset changes getTransitions is what I was looking for! And the offset can change more than one time for a given duration so the offset at start time might be equal to offset at end time but that does guarantee the offset will remain same throughout the given duration and besides I wanna know when precisely in the given duration the offset is going to change! – user1192612 Feb 07 '12 at 20:58
2

This working for me:

function Get_Timezone_Offset($remote_tz, $origin_tz = null) 
{
    if($origin_tz === null) 
    {
        if(!is_string($origin_tz = date_default_timezone_get())) {
            return false;
        }
    }
    $origin_dtz = new DateTimeZone($origin_tz);
    $remote_dtz = new DateTimeZone($remote_tz);
    $origin_dt  = new DateTime("now", $origin_dtz);
    $remote_dt  = new DateTime("now", $remote_dtz);
    $offset     = $origin_dtz->getOffset($origin_dt) - $remote_dtz->getOffset($remote_dt);
    return $offset;
}

To use it

echo Get_Timezone_Offset('America/New_York', 'Europe/Stockholm');

Source: http://php.net/manual/en/function.timezone-offset-get.php

Mohamad Hamouday
  • 2,070
  • 23
  • 20
1

I think PHP's DateTimeZone::getTransitions method can get you there. It has a procedural alias, timezone_transitions_get().

public array DateTimeZone::getTransitions (
    [ int $timestamp_begin [, int $timestamp_end ]]    )

This method returns all "transitions" from one time zone offset value to another, for that timezone, in a given time range.

For your purposes, you will want to create DateTimeZone objects for each of your time zones, call DateTimeZone::getTransitions for your date range to get an array of transitions for that time zone, then merge and sort the two arrays of transitions. This will give you the equivalent of the timezoneoffset[] array you seek.

Something like:

getTimezoneOffset(startDate,endDate,timezone1,timezone2){
    DT1 = DateTimeZone( timezone1 );
    transitions1 = DT1->getTransitions( startDate,endDate );
    DT2 = DateTimeZone( timezone2 );
    transitions1 = DT2->getTransitions( startDate,endDate );
    timezoneoffset[] = // merge and sort (transitions1, transitions2)
}

The format of the transitions array isn't well documented. The method documentation shows some example entries:

Array
(
...
    [1] => Array
        (
            [ts] => -1691964000
            [time] => 1916-05-21T02:00:00+0000
            [offset] => 3600
            [isdst] => 1
            [abbr] => BST
        )

    [2] => Array
        (
            [ts] => -1680472800
            [time] => 1916-10-01T02:00:00+0000
            [offset] => 0
            [isdst] => 
            [abbr] => GMT
        )
    ...
)

I speculate that: ts refers to a PHP timestamp in epoch seconds, as returned by time(), giving the instant in time at which the offset changes to the value in this record. time refers to the same instant, as a formatted string date-time. offset is the timezone's offset in seconds from UTC, as of the instant time/ts, forward to the next transition. isdst is 1 if the offset refers to a daylight savings time offset, 0 otherwise. abbr is a string abbreviation for the time zone. If anyone has solid information about this data structure, it would be a kindness to add it to the documentation.

Jim DeLaHunt
  • 10,960
  • 3
  • 45
  • 74
  • Thanks Jim ..Thats precisely what I was looking for..I went through the datetime object but this got overlooked. – user1192612 Feb 07 '12 at 21:02