Given a Date
, a Time
and a TimeZone
, how can I implement a function that constructs and returns a new Datetime
instance that represents the correct date and time in the specified time zone?
Below is the newDatetime(Date, Time, TimeZone)
method as I have currently coded. As exposed by the two tests, the problem is that the offset calculation will be wrong at some point on the day of a transition in or out of Daylight Savings Time.
@isTest
private class DatetimeUtil2 {
private static DateTime newDatetime(
Date dateValue, Time timeValue, TimeZone zone) {
// Calculate the offset as the number of seconds to add to the GMT
// date and time defined by the `Date` and `Time` values.
Integer offset = -1 * zone.getOffset(dateValue) / 1000 /* ms/sec */;
return DateTime.newInstanceGmt(dateValue, timeValue).addSeconds(offset);
}
@isTest
private static void newDatetime2017Mar12OneAmInAmericaNewYork() {
// Given
Datetime expected = Datetime.newInstanceGmt(2017, 3, 12, 6, 0, 0);
Date givenDate = Date.newInstance(2017, 3, 12);
Time givenTime = Time.newInstance(1, 0, 0, 0);
TimeZone givenTimeZone = TimeZone.getTimeZone('America/New_York');
// When
Test.startTest();
Datetime actual = DatetimeUtil2.newDatetime(
givenDate, givenTime, givenTimeZone);
// Then
Test.stopTest();
System.assertEquals(expected, actual);
}
@isTest
private static void newDatetime2017Mar12ThreeAmInAmericaNewYork() {
// Given
Datetime expected = Datetime.newInstanceGmt(2017, 3, 12, 7, 0, 0);
Date givenDate = Date.newInstance(2017, 3, 12);
Time givenTime = Time.newInstance(3, 0, 0, 0);
TimeZone givenTimeZone = TimeZone.getTimeZone('America/New_York');
// When
Test.startTest();
Datetime actual = DatetimeUtil2.newDatetime(
givenDate, givenTime, givenTimeZone);
// Then
Test.stopTest();
System.assertEquals(expected, actual);
}
}
What seems to be a catch 22 is that ...
- I cannot determine the correct offset without the actual
Datetime
value. This assumes the use ofTimeZone.getOffset
to get the expected offset. - I cannot derive the correct
Datetime
value without the correct offset. This assumes a strategy of first constructing a GMTDatetime
value and then applying the offset.