Parsing an ISO 8601 timestamp to a DateTime
Rich's answer was promising, so I tried to figure out why it wouldn't work, so did a bit of debugging and found that something like this:
System.debug(JSON.deserialize(JSON.serialize(Datetime.now()), Datetime.class));
would print the current Datetime, and that
System.debug(JSON.serialize(Datetime.now());
does in fact serialize to ISo 8601 format, so after a couple of minutes of staring, I realized that the string has to be a valid JSON string, which means, we need double-quotes around it. E.g., try this:
string str = '"2013-01-30T07:38:44.268Z"';
System.debug(JSON.deserialize(str, Datetime.class));
and you should see something like this in the log:
23:40:51.127 (127738280)|USER_DEBUG|[5]|DEBUG|2013-01-30 07:38:44
Or you could just do this:
datetime dt = (datetime)json.deserialize('"2012-07-31T11:22:33.444Z"', datetime.class);
Here's my current technique, but I'm looking for other options. As I put this together, I ran into a bug with the DateTime object, or at least how the JSONParser fills it.
/**
@brief Convert an ISO 8601 timestamp to an Apex \c DateTime value.
Uses the JSONParser getDateTimeValue() method.
See http://en.wikipedia.org/wiki/ISO_8601 for timestamp format details.
Throws a System.JSONException if \p iso8601_ts is not a valid ISO 8601
timestamp.
@param iso8601_ts Valid ISO 8601 timestamp.
@return a \c DateTime value for the given timestamp
*/
public static DateTime convertTimestamp( String iso8601_ts)
{
// Create a valid JSON string like '{"t":"2012-07-31T11:22:33.444Z"}'
JSONParser parser = JSON.createParser( '{"t":"' + iso8601_ts + '"}');
parser.nextToken(); // advance to the start object marker
parser.nextValue(); // advance to the next value
// Bug in JSONParser or DateTime object results in a malformed DateTime,
// so convert to Long and back to DateTime. Without the conversion,
// methods that access timeGmt() and its components will actually get
// local time instead of GMT.
return DateTime.newInstance( parser.getDateTimeValue().getTime());
// Once bug is fixed, this return is preferred.
// return parser.getDateTimeValue();
}
EDIT
Based on feedback from @RichUnger and @haridsv, here's an updated method (opening comments are unchanged). Once the bug is fixed I can simplify it to just return the result of JSON.deserialize()
.
public static DateTime convertISO8601( String iso8601_ts)
{
DateTime dt = (DateTime) JSON.deserialize(
'"' + iso8601_ts + '"', DateTime.class);
// Bug in JSONParser or DateTime object results in a malformed DateTime,
// so convert to Long and back to DateTime. Without the conversion,
// methods that access timeGmt() and its components will actually get
// local time instead of GMT.
return DateTime.newInstance( dt.getTime());
// Once bug is fixed, this return is preferred
// return dt;
}