1

I´m using a third-part service that returns to me dates in this format:

"EndDate":"\/Date(1487615921387-0300)\/","StartDate":"\/Date(1487608721387-0300)\/"

My problem is to convert this date to LocalDate or LocalDateTime. I found some answers here, but they were using joda time, so not helpful.

glennsl
  • 28,186
  • 12
  • 57
  • 75
Rafael Barioni
  • 183
  • 1
  • 1
  • 12

2 Answers2

3

You need to learn the meaning of your input data.

The last part -0300 is likely an offset-from-UTC, a number of hours ahead of or behind UTC. I suggest use the format with a colon (-03:00) but without is acceptable. You need to know if the plus/minus sign means ahead of or behind UTC. Modern protocols tend to use a plus for ahead of UTC and a minus for behind, but there are protocols that do the opposite.

Know that an offset is not a time zone. A time zone is a history of offsets for a particular region with rules for anomalies such as Daylight Saving Time (DST).

The first part is likely a count of milliseconds since an epoch reference date. We can guess that your epoch is the commonly used first moment of 1970 in UTC (1970-01-01T00:00:00). But there are at least a couple dozen epochs used by various known software systems. Again, you must consult the source of your data.

This particular combination of a count-from-epoch with offset I've seen before. It confounds me as it makes more sense to simply use a count-from-epoch in UTC without an offset. If you want to show a date-time adjusted into a time zone, use the standard ISO 8601 string formats.

I will guess that your input number is a count from epoch in milliseconds in UTC. So we parse it as a Instant object. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

String input = "1487615921387-0300";

String inputCount = input.substring ( 0 , 13 ); // zero-based index counting.
long count = Long.parseLong ( inputCount );
Instant instant = Instant.ofEpochMilli ( count );

We can parse the offset as a ZoneOffset object.

String inputOffset = input.substring ( 13 );
ZoneOffset offset = ZoneOffset.of ( inputOffset );

Apply that ZoneId to see the same moment as a wall-clock time in another offset as an OffsetDateTime.

OffsetDateTime odt = instant.atOffset ( offset );

See this code run live at IdeOne.com.

input: 1487615921387-0300

inputMillis: 1487615921387

inputOffset: -0300

count: 1487615921387

instant.toString(): 2017-02-20T18:38:41.387Z

odt.toString(): 2017-02-20T15:38:41.387-03:00

Note the three hour difference between instant and odt, hours 18 versus 15, the effect of the offset. Still the same simultaneous moment, same point on the timeline, but seen with a different wall-clock time.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    You are correct in your assumptions. The first part is milliseconds since unix epoch. The second part is local offset, in +/-hhmm format, with positive values leading east of UTC like the ISO standard. This stupid format came from the `JavaScriptSerializer` class in .NET, and [is widely recognized as an abomination](http://www.hanselman.com/blog/OnTheNightmareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx). We call it an "ASP.NET JSON Date" [in moment.js](http://momentjs.com/docs/#/parsing/asp-net-json-date/). Modern .NET doesn't use it any more. – Matt Johnson-Pint Feb 21 '17 at 00:19
  • @MattJohnson But if the number is a count-from-epoch of UTC, what is the point of the offset? Append an offset to a UTC value adds no value since anyone can apply any offset they want to a UTC value. – Basil Bourque Feb 21 '17 at 01:59
  • One can still use it to reconstruct a date-time-offset value. Just that normally we see the date-time portion already converted to local time of the offset - in this case the date-time portion is UTC. – Matt Johnson-Pint Feb 21 '17 at 02:27
0

Ok first you should to extract your Dates from your String i use a patttern the idea is simple

public static void main(String[] args) {

    String str = "\"EndDate\":\"\\/Date(1487615921387-0300)\\/\",\"StartDate\":\"\\/Date(1487608721387-0300)\\/\"";
    //Get Long from your String between Date( and )
    String start = "Date(", end = ")";
    String regexString = Pattern.quote(start) + "(.*?)" + Pattern.quote(end);
    Pattern pattern = Pattern.compile(regexString);
    Matcher matcher = pattern.matcher(str);
    List<String> res = new ArrayList<>();
    while (matcher.find()) {
        //now we get results like this 1487608721387-0300
        res.add(matcher.group(1));
    }

    //You can change the format like you want
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    Date date;
    String[] split;
    for (String s : res) {
        split = s.split("-");
        ///we should to split the String to get the first part 1487608721387
        //then we get Date from this String
        date = new Date(new Long(split[0]));
        //Set time zone to your format i'm not sure if it is correct you can avoid it
        //format.setTimeZone(TimeZone.getTimeZone(split[1]));
        //Show your date
        System.out.println(format.format(date));
    }
}
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140