tl;dr
- Feature, not a bug.
- Your number
1_503_979_200_000L
is a count of milliseconds from 1970-01-01T00:00:00Z.
Tips:
- Use java.time classes instead of legacy date-time classes.
- Use ISO 8601 formats when serializing date-time values to text.
Count-from-epoch
Your java.util.Date
object is being serialized as a count of milliseconds since the epoch reference moment of first moment of 1970 in UTC, 1970-01-01T00:00:00Z. Sometimes called Unix Time, or POSIX Time.
java.time
The java.util.Date
class you are using is one of the terrible old date-time classes bundled with the earliest versions of Java. Do not use these classes! Years ago they were supplanted by the java.time classes built into Java 8 and later.
Specifically, Date
was replaced by Instant
. Both represent a moment in UTC, but Instant
resolves to the finer level of nanoseconds rather than milliseconds.
long input = 1_503_979_200_000L;
Instant instant = Instant.ofEpochMilli( input );
instant.toString(): 2017-08-29T04:00:00Z
According to the Answer on my Question, JAXB has not yet been updated for java.time. However, adapters are available, such as this one.
ISO 8601
The ISO 8061 standard defines practical useful formats for serializing date-time values as text. They are easy to parse by machine. They are easy to read by humans across cultures.
The java.time classes use these formats by default when parsing/generating strings.
Example app
Here is a simple little example app to demonstrate how to use the java.time class Instant
.
We added the JAXB adapters for Java 8 Date and Time API (JSR-310) types library via Maven. We need this adapter for Instant
as JAXB has not yet been updated for java.time types. Hopefully that update can happen if we see swifter development with the Jakarta EE organization.
<dependency>
<groupId>com.migesok</groupId>
<artifactId>jaxb-java-time-adapters</artifactId>
<version>1.1.3</version>
</dependency>
First, our simple little business-object class Event
with a pair of properties, when
and description
.
package com.basilbourque.example;
import com.migesok.jaxb.adapter.javatime.InstantXmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.time.Instant;
public class Event {
private Instant when;
private String description;
// ---------------| Constructors |-------------------------
public Event ( Instant when , String description ) {
this.when = when;
this.description = description;
}
// ---------------| Accessors |-------------------------
@XmlJavaTypeAdapter ( InstantXmlAdapter.class )
public Instant getWhen () {
return when;
}
public void setWhen ( Instant when ) {
this.when = when;
}
public String getDescription () {
return description;
}
public void setDescription ( String description ) {
this.description = description;
}
// ---------------| Object |-------------------------
@Override
public String toString () {
return "Event{ " +
"when=" + when +
", description='" + description + '\'' +
" }";
}
}
Instantiate a business object.
Event e = new Event( Instant.now() , "Devoxx" );
System.out.println("e.toString(): " + e);
System.out.println(""); // blank line.
e.toString(): Event{ when=2018-07-31T04:03:43.113356Z, description='Devoxx' }
Run our JAXB code.
try {
JAXBContext jc = JAXBContext.newInstance( Event.class );
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT , true );
JAXBElement< Event > jaxbElement = new JAXBElement< Event >( new QName( "event" ) , Event.class , e );
marshaller.marshal( jaxbElement , System.out );
} catch ( JAXBException e1 ) {
e1.printStackTrace();
}
Results:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<event>
<description>Devoxx</description>
<when>2018-07-31T04:03:43.113356Z</when>
</event>
We see the standard ISO 8601 format was used in the XML, 2018-07-31T04:03:43.113356Z
. The Z
on the end means UTC, and is pronounced Zulu
.
Much more readable than 1503979200000
!
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.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
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.