1

We have used below code to covert time in different timezones, but unfortunately even if Salesforce claims to handle daylight saving adjustment, it's not considering day light saving offsets

Expected Offset : -25200000

Actual offset : -28800000

Can someone give me some hint?

Timezone tzUsr = TimeZone.getTimeZone('America/Los_Angeles');
Datetime myDate = Datetime.newInstance(2016, 12, 22, 9, 0, 0);

Integer OffsetpresentDate = tzUsr.getOffset(myDate); 

Integer minuteDiff = OffsetpresentDate/60000;
Datetime convertedDateTime = myDate.addminutes(minuteDiff);

o/p which I get :-

myDate:2016-12-22 03:30:00

OffsetpresentDate:-28800000

convertedDateTime:2016-12-21 19:30:00

Expected : convertedDateTime:2016-12-21 20:30:00

2 Answers 2

1

You seem to have a fundamental misunderstanding of how the offset calculation works. Have a look at the documentation for the TimeZone class (emphasis mine):

getOffset(date)
Returns the time zone offset, in milliseconds, of the specified date to the GMT time zone.
...
Usage
The returned offset is adjusted for daylight saving time if the date argument falls within daylight saving time for this time zone.

So if you specify a combination of TimeZone and Datetime that falls within Daylight Savings Time, this method calculates the daylight savings offset. Otherwise, it calculates the standard offset.


In light of the above, you are incorrect about your expected offset. On December 21st of 2016, Los Angeles was on Pacific Standard Time, for which the UTC offset is -8.

If you look at the conversion, -8 hours = -480 minutes = -28800000 milliseconds. The correct offset is to subtract 8 hours, which is what you're seeing. Salesforce behavior is correct, it's your expected value that needs adjustment.


There are plenty of tables out there which you can use to determine when Daylight Savings Time starts and ends. I found one here:

Year    DST Begins at 2 a.m.    DST Ends at 2 a.m.
2009    March 08                November 1
2010    March 14                November 7
2011    March 13                November 6
2012    March 11                November 4
2013    March 10                November 3
2014    March 09                November 2
2015    March 08                November 1
2016    March 13                November 6
2017    March 12                November 5
2018    March 11                November 4
2019    March 10                November 3
2020    March 8                 November 1
2021    March 14                November 7

As you can see from the above table, any date between 2016-11-06 and 2017-03-12 in America/Los_Angeles observes Standard Time, not Daylight Savings Time.


The above dates line up exactly with the offset calculated by Salesforce. You can see for yourself by executing this script in Execute Anonymous:

static Integer getPacificOffset(Integer year, Integer month, Integer day)
{
    return TimeZone.getTimeZone('America/Los_Angeles')
        .getOffset(Datetime.newInstanceGmt(year, month, day)) /
        (1000 * 60 * 60);
}

system.debug(2014);
system.debug(getPacificOffset(2014, 3, 9)); // -8
system.debug(getPacificOffset(2014, 3, 10)); // -7
system.debug(getPacificOffset(2014, 11, 2)); // -7
system.debug(getPacificOffset(2014, 11, 3)); // -8

system.debug(2015);
system.debug(getPacificOffset(2015, 3, 8)); // -8
system.debug(getPacificOffset(2015, 3, 9)); // -7
system.debug(getPacificOffset(2015, 11, 1)); // -7
system.debug(getPacificOffset(2015, 11, 2)); // -8

system.debug(2016);
system.debug(getPacificOffset(2016, 3, 13)); // -8
system.debug(getPacificOffset(2016, 3, 14)); // -7
system.debug(getPacificOffset(2016, 11, 6)); // -7
system.debug(getPacificOffset(2016, 11, 7)); // -8
1
  • Could you please help in handling such situation in apex class? We are actually considering that Salesforce will handle to calculate right Offset like in PST : UTC - 8 and in PDT UTC -7 Commented Dec 26, 2016 at 6:58
1

In addition to Adrian's excellent answer, perhaps this can help

My UTIL class used to take a local timezone + date + time and convert to a GMT value

//  ------------------------------------------------------------------
//  getDateTimeGmt  : Returns a datetime in GMT from a timezoneId, date and time object
//   Example: getDateTimeGmt('America/Los_Angeles',someDate,someTime)
//  ------------------------------------------------------------------
public static Datetime getDateTimeGmt(String tzId, Date d, Time t) {
    DateTime    res;
    if (tzId == null || d == null || t == null) return res;
    Timezone    tz          = Timezone.getTimeZone(tzId);
    DateTime    dt          = DateTime.newInstanceGmt(d,t);
    Integer     offsetMs    = tz.getOffset(dt);                 // #ms offset from datetime in Tz to GMT
    Integer     offsetMins  = offsetMs / (1000 * 60);
    res = dt.addMinutes(-1 * offsetMins);

    return res;
}

//  testGetDateTimeGmt
@isTest
private static void testGetDateTimeGmt() {
    String  tz;
    Date    d;
    Time    t;

    //  Verify Pacific Std (January) and DST (May)
    System.assertEquals(DateTime.newInstanceGmt(2020,1,1,19,0,0),   Util.getDateTimeGmt('America/Los_Angeles',Date.newInstance(2020,1,1),Time.newInstance(11,0,0,0)),'sb offset by -8 hours - not DST');
    System.assertEquals(DateTime.newInstanceGmt(2020,5,1,18,0,0),   Util.getDateTimeGmt('America/Los_Angeles',Date.newInstance(2020,5,1),Time.newInstance(11,0,0,0)),'sb offset by -7 hours -  DST');
    System.assertEquals(DateTime.newInstanceGmt(2020,5,2,4,0,0),    Util.getDateTimeGmt('America/Los_Angeles',Date.newInstance(2020,5,1),Time.newInstance(21,0,0,0)),'sb offset by -7 hours -  DST but GMT is next day');

    // Go the other way - Europe/Paris
    System.assertEquals(DateTime.newInstanceGmt(2020,1,1,10,0,0),   Util.getDateTimeGmt('Europe/Paris',Date.newInstance(2020,1,1),Time.newInstance(11,0,0,0)),'sb offset by +1 hours - not DST');
    System.assertEquals(DateTime.newInstanceGmt(2020,6,1,9,0,0),    Util.getDateTimeGmt('Europe/Paris',Date.newInstance(2020,6,1),Time.newInstance(11,0,0,0)),'sb offset by +2 hours - DST');
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .