Here is an updated work in progress using anonymous apex to convert from the time in New York to UTC. Note that the assertions after the daylight savings change occurs are currently failing. It appears that the getOffset()
method is detecting the DST change from the perspective of a UTC input rather than the target timezones input. I.e. The offset will change between 5:59 am and 6 am in UTC rather than between 1:59 am and 2 am EST. I need to find a way to reverse the offset.
TimeZone tz = UserInfo.getTimeZone();
System.assertEquals('New Zealand Standard Time', tz.getDisplayName(), 'Proving the current user is in a completely different timezone');
string customerTimeZoneSidId = 'America/New_York';
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 0, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-01 20:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 1, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-01 21:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 2, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-01 22:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 3, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-01 23:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 4, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-02 0:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-02 1:00:00'), 'Sunday, 2 November 2014 at 1:00:00 a.m.');
// http://www.timeanddate.com/worldclock/converted.html?iso=20141102T02&p1=179&p2=0
// Should be UTC - 5 hours
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-02 2:00:00'), 'Sunday, 2 November 2014 at 2:00:00 a.m');
// http://www.timeanddate.com/worldclock/converted.html?iso=20141102T03&p1=179&p2=0
// Should be UTC - 5 hours
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0), toUtc(customerTimeZoneSidId, '2014-11-02 3:00:00'), 'Sunday, 2 November 2014 at 3:00:00 a.m.');
public DateTime toUtc(string customerTimeZone, string timeZoneString) {
DateTime customerDateTime = DateTime.valueofGmt(timeZoneString);
integer offsetToUtc = TimeZone.getTimeZone(customerTimeZone).getOffset(customerDateTime);
System.debug('GMT Offset: ' + offsetToUtc + ' (milliseconds) to ');
DateTime utcDateTime = customerDateTime.addMinutes(-1 * offsetToUtc / (1000 * 60));
return utcDateTime;
}
The following is a subset of the answer to convert time from a different timezone other than local to GMT. Using the date time input and the corresponding TimeZoneSid with the TimeZone class introduced in Spring 13 you can adjust the value to UTC. The getOffset()
metthod with return the time zone offset in milliseconds to the GMT time zone.
// This is the Date and Time in the customers TimeZone. It might differ to the current users timezone.
string customerDateTimeString = '2014-10-22 12:12:00';
DateTime customerDateTime = DateTime.valueofGmt(customerDateTimeString);
string customerTimeZoneSidId = 'America/Los_Angeles';
TimeZone customerTimeZone = TimeZone.getTimeZone(customerTimeZoneSidId);
System.assertEquals('Pacific Standard Time', customerTimeZone.getDisplayName());
integer offsetToCustomersTimeZone = customerTimeZone.getOffset(customerDateTime);
System.debug('GMT Offset: ' + offsetToCustomersTimeZone + ' (milliseconds) to PST');
// For the given Date I expect PDT to be GMT - 7 hours
System.assertEquals(-7, offsetToCustomersTimeZone / (1000 * 60 *60));
// Figure out correct to go from Customers DateTime to GMT and then from GMT to Users TimeZone
integer correction = - offsetToCustomersTimeZone;
System.debug('correction to UTC: ' + correction);
// Note: Potential issues for TimeZone differences less than a minute
DateTime utcDateTime = customerDateTime.addMinutes(correction / (1000 * 60));
System.debug('utcDateTime: ' + utcDateTime);
// In the UTC timezone the time should be moved forward 7 hours
System.assertEquals(utcDateTime, DateTime.valueofGmt('2014-10-22 19:12:00'));