I opened a case with Salesforce (#08078994), but their Support Engineer has claimed repeatedly that, "I have reconfirmed and there is no issue with Date Time methods. The issue which you are notifying to us is related to coding done by you."
Am I really doing something wrong here? I'm trying to show that when I use JSON.createParser()
to build a DateTime
value, it's garbled. The formatGmt()
method shows the correct time, but hourGmt()
returns a different value (the local hour instead of GMT).
The code I wrote for this StackExchange answer to my question about parsing an ISO 8601 timestamp was affected by the bug.
String iso8601 = '2012-07-31T11:22:33.444Z';
JSONParser parser = JSON.createParser( '{"t":"' + iso8601 + '"}');
parser.nextToken();
parser.nextValue();
DateTime dt1 = parser.getDateTimeValue();
// dt2 should be identical to dt1
DateTime dt2 = DateTime.newInstance( dt1.getTime());
String timeformat = 'M/d/yyyy h:mm a';
System.Debug( iso8601 + ' parsed as ' + dt1);
System.Assert( dt1.format() == dt2.format()); // localtime is the same
System.Assert( dt1.getTime() == dt2.getTime()); // same number of milliseconds since epoch
System.Assert( dt1.formatGmt( timeformat) == dt2.formatGmt( timeformat));
System.Assert( dt1.hourGmt() == dt2.hourGmt()); // assertion fails when it should not
EDIT
This is still broken in Winter '12, I have not had an opportunity to test it in Spring '13 yet. Here's a simplified example, that eliminates the dual DateTime objects and uses a single call to JSON.deserialize:
String iso8601 = '2012-07-31T11:22:33.000Z';
DateTime dt1 = (DateTime) JSON.deserialize( '"' + iso8601 + '"', DateTime.class);
String timeformat = 'M/d/yyyy h:mm a';
System.Debug( iso8601 + ' parsed as ' + dt1);
System.assertEquals( '7/31/2012 11:22 AM', dt1.formatGmt( timeformat), 'not parsed correctly');
System.assertEquals( 11, dt1.hourGmt(), 'hourGmt should be 11');
And the output:
USER_DEBUG|[7]|DEBUG|2012-07-31T11:22:33.000Z parsed as 2012-07-31 11:22:33
EXCEPTION_THROWN|[10]|System.AssertException: Assertion Failed: hourGmt should be 11: Expected: 11, Actual: 4
I think the key here is that formatGmt()
prints an hour of 11, but hourGmt()
returns 4, the same as hour()
.
And oddly, I can kind of "reset" the DateTime object using this construct:
dt1 = DateTime.newInstance( dt1.getTime());
If I add that before the assert
in my test code, it passes.
EDIT
Still broken in Winter '13.
formatGmt()
andgetTime()
(which returns milliseconds since 1/1/1970 GMT) return the same values, then why doesn'thourGmt()
? – tomlogic Oct 3 '12 at 2:49