简体   繁体   中英

Convert JSON date format

I'm receiving a JSON object with date value like this:

{"PostingDate":"\/Date(1325134800000-0500)\/"}

And I want to parse it in Java code to Date or getting it as a String .

I want to know what is the easy way of doing it.

I take it the first number ( 1325134800000 ) is the number of milliseconds since epoch, and -0500 is the time zone. This appears to be the case given the sample code below, which seems to do what you want.

The following code parses the JSON input using Jackson , which I recommend if you don't have a JSON parsing library of choice yet. It lacks error checking etc.

Sample code:

public final class Foo
{
    public static void main(final String... args)
        throws IOException
    {
        // What the JSON value must match exactly
        // Not anchored since it will be used with the (misnamed) .matches() method
        final Pattern pattern
            = Pattern.compile("\\\\/Date\\((\\d+)(-\\d+)?\\)\\\\/");

        final ObjectMapper mapper = new ObjectMapper();

        // Parse JSON...
        final JsonNode node = mapper.readTree(
            "{\"PostingDate\": \"\\/Date(1325134800000-0500)\\/\"}");

        if (!node.has("PostingDate")) {
            System.err.println("Bad JSON input!");
            System.exit(1);
        }

        // Get relevant field
        final String dateSpec = node.get("PostingDate").getTextValue();

        // Try and match the input.
        final Matcher matcher = pattern.matcher(dateSpec);

        if (!matcher.matches()) {
            System.err.println("Bad pattern!"); // Yuck
            System.exit(1);
        }

        // The first group capture the milliseconds, the second one the time zone

        final long millis = Long.parseLong(matcher.group(1));
        String tz = matcher.group(2);
        if (tz.isEmpty()) // It can happen, in which case the default is assumed to be...
            tz = "+0000";

        // Instantiate a date object...    
        final Date date = new Date(millis);

        // And print it using an appropriate date format
        System.out.printf("Date: %s %s\n",
            new SimpleDateFormat("yyyy/MM/dd HH:MM:ss").format(date), tz);
    }
}

Output:

Date: 2011/12/29 06:12:00 -0500

Hier is a working parsing method based on the version of fge but improved as

  1. it used jode's DateTime with the correct timezone initialized
  2. minor change to pattern to accept +0200 too

=>

private static final Pattern bingTimePattern = Pattern.compile("\\/Date\\((\\d+)([-+]\\d+)?\\)\\/");

public static DateTime parseBingTime(String timeAsString) throws ParseException {
    Matcher matcher = bingTimePattern.matcher(timeAsString);
    if (!matcher.find())
        throw new ParseException("wrong date time format " + timeAsString, 0);

    final long millis = Long.parseLong(matcher.group(1));
    String tz = matcher.group(2);
    if (tz.isEmpty())
        tz = "+0000";

    return new DateTime(millis, DateTimeZone.forID(tz));
}

I have created a simple JavaScript function using Jquery DatePicker

  function JsonToJSDate(jsonDate) { var reg = /-?\\d+/; var m = reg.exec(jsonDate); return new Date(parseInt(m[0])); } 

$('#Started').val($.datepicker.formatDate('mm/dd/yy', JsonToJSDate(yourDateVarHere)));

Simple thing but handling my job. Extract your object value from JSON and apply substring.
eg:

      String postingDateObjectValue = "\\/Date(1442436473422)\\/";

      String dateStringInMillis = postingDateObjectValue .substring(7,20);

now parse millis and use them where ever you want.

In Java >= 8 you can use the new java.time API .

The input contains:

  • a unix timestamp ( 1325134800000 ), which is the number of milliseconds since unix epoch ( 1970-01-01T00:00Z )
  • a UTC offset ( -0500 ), which is the difference from UTC (in this case, 5 hours behind UTC)

In the new java.time API, there are lots of different types of date/time objects. In this case, we can choose to use a java.time.Instant (which represent a count of nanoseconds since unix epoch) or a java.time.OffsetDateTime (which represents the Instant converted to a date/time in a specific offset).

To parse the String , I use a java.time.format.DateTimeFormatterBuilder to create a java.time.format.DateTimeFormatter . I also use a java.time.temporal.ChronoField to specify which fields I'm parsing:

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // epoch seconds
    .appendValue(ChronoField.INSTANT_SECONDS)
    // milliseconds
    .appendValue(ChronoField.MILLI_OF_SECOND, 3)
    // offset
    .appendPattern("xx")
    // create formatter
    .toFormatter();

I also use a regex to extract just the relevant part from the input String (although you could also use substring() to get it):

String s = "/Date(1325134800000-0500)/";

// get just the "1325134800000-0500" part - you can also do s.substring(6, 24)
s = s.replaceAll(".*/Date\\(([\\d\\+\\-]+)\\)/.*", "$1");

Then I can parse to the type I want:

// parse to Instant
Instant instant = Instant.from(fmt.parse(s));
// parse to OffsetDateTime
OffsetDateTime odt = OffsetDateTime.parse(s, fmt);

The Instant is equivalent to 2011-12-29T05:00:00Z ( Instant is just a point in the timeline, and you can think that's always in UTC). The OffsetDateTime has the same instant, but converted to -0500 offset, so its value is 2011-12-29T00:00-05:00 . But both Instant and OffsetDateTime represents the same point in time.


To convert to java.util.Date , use the Instant :

// convert to java.util.Date
Date date = Date.from(instant);

// if you have an OffsetDateTime, you can do this:
Date date = Date.from(odt.toInstant());

That's because the java.util.Date has no timezone/offset information and it just represents the count of milliseconds since unix epoch (the same concept of Instant ), so it can be easily converted from an Instant .


Java 6 and 7

For Java 6 and 7, you can use the ThreeTen Backport , a great backport for Java 8's new date/time classes. And for Android , you'll also need the ThreeTenABP (more on how to use it here ).

The difference from Java 8 is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp ), but the classes and methods names are the same. So the formatter creation and the parsing code to Instant and OffsetDateTime are the same.

Another difference is that, in Java <= 7, the java.util.Date class has no from() method. But you can use the org.threeten.bp.DateTimeUtils class to do the conversion:

// convert to java.util.Date
Date date = DateTimeUtils.toDate(instant);

// or from the OffsetDateTime
Date date = DateTimeUtils.toDate(odt.toInstant());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM