Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

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() from JSONParser.
share|improve this question
add comment

3 Answers 3

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
share|improve this answer
    
Excellent! +1 to you and @RichUnger for the combined effort. –  tomlogic Jan 30 '13 at 17:53
add comment

Or you could just do:

datetime dt = (datetime)json.deserialize('2012-07-31T11:22:33.444Z', datetime.class);

share|improve this answer
1  
I was so hopeful for that technique, but it didn't work in my quick test: 2012-07-31T11:22:33.444Z parsed as 2011-12-31 23:00:00. JSON must not use ISO 8601 for serializing DateTime objects. –  tomlogic Aug 31 '12 at 17:05
    
@tomlogic see my answer on why it didn't work for you. –  haridsv Jan 30 '13 at 7:49
add comment
up vote 1 down vote accepted

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;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.