I've written a simple method to parse a specific kind of ISO 8601 timestamp (GMT, with milliseconds), into a DateTime.
I'm looking to replace it with something that can parse any ISO 8601 timestamp (with or without element separators, missing elements like seconds or milliseconds, with timezone, etc.) Rather that re-inventing the wheel, I'm wondering about using a built-in method.
A similar question about converting ISO 8601 timestamps in Java on Stack Overflow pointed out that, "JAXB must be able to parse ISO8601 date string according to the XML Schema specification".
I don't know what JAXB is, or whether it's available from Apex, but I do know that Apex has all sorts of XML parsers and WSDL tools. The XMLNode class doesn't have an ISO 8601 parser, but I did find mention of one as part of the JSONParser class (getDatetimeValue()
method), and I plan to use that in a wrapper for my conversion.
I'm wondering:
- If there's something simpler.
- If there are known limitations of
getDatetimeValue()
fromJSONParser
.
Attribution to: tomlogic
Possible Suggestion/Solution #1
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
Attribution to: haridsv
Possible Suggestion/Solution #2
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;
}
Attribution to: tomlogic
Possible Suggestion/Solution #3
Or you could just do this:
datetime dt = (datetime)json.deserialize('"2012-07-31T11:22:33.444Z"', datetime.class);
Attribution to: Rich Unger
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/1013