Skip to main content
added 1454 characters in body
Source Link
Daniel Ballinger
  • 103k
  • 40
  • 275
  • 601

Transition into Summer Time (losing 1 hour):

customerTimeZoneSidId = 'Europe/Lisbon';
//http://www.timeanddate.com/worldclock/converted.html?iso=20140330T02&p1=133&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 29, 23, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-29 23:00:00')); 

System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 0, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 00:00:00')); 
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 0, 59, 0), toUtc(customerTimeZoneSidId, '2014-03-30 00:59:00')); 

// http://www.timeanddate.com/worldclock/converted.html?iso=20140330T01&p1=133&p2=0
// The time Sunday, 30 March 2014 at 1:00:00 a.m. does not exist in Lisbon. 
// Daylight Saving Time skipped one hour.
//System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 0, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 01:00:00')); // Will Fail 

//http://www.timeanddate.com/worldclock/converted.html?iso=20140330T02&p1=133&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 1, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 02:00:00')); 
//http://www.timeanddate.com/worldclock/converted.html?iso=20140330T03&p1=133&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 2, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 03:00:00')); 
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 3, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 04:00:00')); 

Transition into Summer Time (losing 1 hour):

customerTimeZoneSidId = 'Europe/Lisbon';
//http://www.timeanddate.com/worldclock/converted.html?iso=20140330T02&p1=133&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 29, 23, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-29 23:00:00')); 

System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 0, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 00:00:00')); 
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 0, 59, 0), toUtc(customerTimeZoneSidId, '2014-03-30 00:59:00')); 

// http://www.timeanddate.com/worldclock/converted.html?iso=20140330T01&p1=133&p2=0
// The time Sunday, 30 March 2014 at 1:00:00 a.m. does not exist in Lisbon. 
// Daylight Saving Time skipped one hour.
//System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 0, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 01:00:00')); // Will Fail 

//http://www.timeanddate.com/worldclock/converted.html?iso=20140330T02&p1=133&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 1, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 02:00:00')); 
//http://www.timeanddate.com/worldclock/converted.html?iso=20140330T03&p1=133&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 2, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 03:00:00')); 
System.assertEquals(DateTime.newInstanceGMT(2014, 3, 30, 3, 0, 0), toUtc(customerTimeZoneSidId, '2014-03-30 04:00:00')); 
added 2967 characters in body
Source Link
Daniel Ballinger
  • 103k
  • 40
  • 275
  • 601

Extra test cases you can try:

customerTimeZoneSidId = 'America/El_Salvador'; // San Salvador, El Salvador
//http://www.timeanddate.com/worldclock/converted.html?iso=20141101T18&p1=228&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 0, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 18:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 1, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 19:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 2, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 20:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 3, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 21:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 4, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 22:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 23:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 6, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 0:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 1:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 59, 0), toUtc(customerTimeZoneSidId, '2014-11-02 1:59:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 2:00:00'));

customerTimeZoneSidId = 'Asia/Kathmandu'; // Nepal
//http://www.timeanddate.com/worldclock/converted.html?iso=20141102T1045&p1=117&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 10:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 6, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 11:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 12:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 13:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 9, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 14:45:00'));

customerTimeZoneSidId = 'America/Chicago'; // Central Standard Time
//http://www.timeanddate.com/worldclock/converted.html?iso=20141102T00&p1=64&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 0:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 6, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 1:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 2:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 9, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 3:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 10, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 4:00:00'))

Extra test cases you can try:

customerTimeZoneSidId = 'America/El_Salvador'; // San Salvador, El Salvador
//http://www.timeanddate.com/worldclock/converted.html?iso=20141101T18&p1=228&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 0, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 18:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 1, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 19:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 2, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 20:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 3, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 21:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 4, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 22:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-01 23:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 6, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 0:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 1:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 59, 0), toUtc(customerTimeZoneSidId, '2014-11-02 1:59:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 2:00:00'));

customerTimeZoneSidId = 'Asia/Kathmandu'; // Nepal
//http://www.timeanddate.com/worldclock/converted.html?iso=20141102T1045&p1=117&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 10:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 6, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 11:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 7, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 12:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 13:45:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 9, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 14:45:00'));

customerTimeZoneSidId = 'America/Chicago'; // Central Standard Time
//http://www.timeanddate.com/worldclock/converted.html?iso=20141102T00&p1=64&p2=0
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 0:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 6, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 1:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 8, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 2:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 9, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 3:00:00'));
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 10, 0, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 4:00:00'))
deleted 343 characters in body
Source Link
Daniel Ballinger
  • 103k
  • 40
  • 275
  • 601

Here is an updated work in progress usingThe following anonymous apex uses TimeZone.getOffset() 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

My current solution for this is to check the reverse offset once in UTC. If it differs for the original offset use the corrected UTC offset.

If I create a UTC DateTime for the 2nd of November 2014 at 2:00:00 a.m in EST then getOffset will return 4 hours. Checking the offset again from the 2nd of November 2014 at 6:00:00 a.m in UTC shows an offset of 5 hours. So we should actually use the 5 hour offset to determine the correct UTC value.

TimeZone tz = UserInfo.getTimeZone();
// Your results for this assertion will of course vary.
System.assertEquals('New Zealand Standard Time', tz.getDisplayName(), 'Proving the current user is in a completely different timezone'timezone to UTC and the source 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.');
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 59, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 1:59:00'), 'Sunday, 2 November 2014 at 1:59:00 a.m.');

// Note, skips 6 am UTC to 7 am UTC

// 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);
    
    integerTimeZone offsetToUtcctz = TimeZone.getTimeZone(customerTimeZone);

    integer offsetToUtc = ctz.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 isReverse thecheck Dateas andgetOffset Timewill inbe theworking customersagainst TimeZoneUTC. ItWe mightcan't differcreate toan instance in the currentcustomers userstime timezonezone.
string customerDateTimeString = '2014-10-22 12:12:00';
DateTime customerDateTime// =May DateTime.valueofGmt(customerDateTimeString);
stringneed customerTimeZoneSidIdto =use 'America/Los_Angeles';

TimeZonethe customerTimeZonerevised =UTC TimeZone.getTimeZone(customerTimeZoneSidId);
System.assertEquals('Pacificoffset Standardonce Time',we can customerTimeZone.getDisplayName());

integeractaully offsetToCustomersTimeZonework =from customerTimeZoneUTC.getOffset(customerDateTime);
System.debug('GMT Offset: ' + offsetToCustomersTimeZoneinteger +utcOffset '= ctz.getOffset(milliseconds) to PST'utcDateTime);
 
// For the given Date I expect PDT to be GMT//DateTime -revisedCustomerDateTime 7= hours
SystemutcDateTime.assertEqualsaddMinutes(-7, offsetToCustomersTimeZoneutcOffset / (1000 * 60 *60));
 
    // FigureExercise outfor correctthe toreader, gocheck fromwhat Customersoccurs DateTimewith tothe GMTother andDST thentransition
 from GMT to Usersif(offsetToUtc TimeZone!= utcOffset) {
integer correction = - offsetToCustomersTimeZone;
    System.debug('correctionLoggingLevel.Warn, to'Revised UTC: offset to ' + correctionutcOffset);
 
// Note: Potential issues for TimeZone differences less than a minute
DateTime utcDateTime = customerDateTime.addMinutes(correction-1 * utcOffset / (1000 * 60));
    }
    
    System.debug('utcDateTime:'Converted ' + utcDateTime);
//customerDateTime In+ the' UTCto timezone' the+ timeutcDateTime);
 should be moved forward 
 7 hours
System.assertEquals(utcDateTime, DateTime.valueofGmt('2014-10-22 19:12:00'));return utcDateTime;
}

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'));

The following anonymous apex uses TimeZone.getOffset() to convert from the time in New York to UTC. Note 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.

My current solution for this is to check the reverse offset once in UTC. If it differs for the original offset use the corrected UTC offset.

If I create a UTC DateTime for the 2nd of November 2014 at 2:00:00 a.m in EST then getOffset will return 4 hours. Checking the offset again from the 2nd of November 2014 at 6:00:00 a.m in UTC shows an offset of 5 hours. So we should actually use the 5 hour offset to determine the correct UTC value.

TimeZone tz = UserInfo.getTimeZone();
// Your results for this assertion will of course vary.
System.assertEquals('New Zealand Standard Time', tz.getDisplayName(), 'Proving the current user is in a completely different timezone to UTC and the source 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.');
System.assertEquals(DateTime.newInstanceGMT(2014, 11, 2, 5, 59, 0),  toUtc(customerTimeZoneSidId, '2014-11-02 1:59:00'), 'Sunday, 2 November 2014 at 1:59:00 a.m.');

// Note, skips 6 am UTC to 7 am UTC

// http://www.timeanddate.com/worldclock/converted.html?iso=20141102T02&p1=179&p2=0
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
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);

    TimeZone ctz = TimeZone.getTimeZone(customerTimeZone);

    integer offsetToUtc = ctz.getOffset(customerDateTime);

    //System.debug('GMT Offset: ' + offsetToUtc + ' (milliseconds) ');

    DateTime utcDateTime = customerDateTime.addMinutes(-1 * offsetToUtc / (1000 * 60));
    
    // Reverse check as getOffset will be working against UTC. We can't create an instance in the customers time zone.
    // May need to use the revised UTC offset once we can actaully work from UTC.
    integer utcOffset = ctz.getOffset(utcDateTime);
    //DateTime revisedCustomerDateTime = utcDateTime.addMinutes(utcOffset / (1000 * 60));
    // Exercise for the reader, check what occurs with the other DST transition
    if(offsetToUtc != utcOffset) {
        System.debug(LoggingLevel.Warn, 'Revised UTC offset to ' + utcOffset);
        utcDateTime = customerDateTime.addMinutes(-1 * utcOffset / (1000 * 60));
    }
    
    System.debug('Converted ' + customerDateTime + ' to ' + utcDateTime);
     
    return utcDateTime;
}
added 195 characters in body
Source Link
Daniel Ballinger
  • 103k
  • 40
  • 275
  • 601
Loading
added 2331 characters in body
Source Link
Daniel Ballinger
  • 103k
  • 40
  • 275
  • 601
Loading
Source Link
Daniel Ballinger
  • 103k
  • 40
  • 275
  • 601
Loading