Integration with Java

Table Of Contents

Bridge to java.util.Date
How to convert between java.util.Date and local types?
Interoperability with Java 8 (in version line 4.x)


All support for other temporal types is centralized in the special conversion class TemporalType and its subtypes. These classes allow conversion between the external type S and Time4J-type T. For the direction T => S, you simply use the method from(T). The method translate(S) realizes the reverse direction.

Bridge to java.util.Date

This is mainly realized by the element constant TemporalType.JAVA_UTIL_DATE which performs a transformation between the global types java.util.Date and Moment. Note that this transformation is sometimes lossy: Leap seconds will get lost as well as micro- or nanoseconds.

	// S => T
	java.util.Date jud = new java.util.Date(0L);
	Moment moment = TemporalType.JAVA_UTIL_DATE.translate(jud); // 1970-01-01T00:00:00,000000000Z

	// T => S
	Moment moment = Moment.of(0, 123456789, TimeScale.POSIX);
	java.util.Date jud = TemporalType.JAVA_UTIL_DATE.from(moment); // 1970-01-01T00:00:00,123000000Z

There is also direct support for the interpretation of the count of milliseconds since UNIX-epoch as long via the element constant MILLIS_SINCE_UNIX which performs a transformation to the class Moment, too.


The mapping between JDBC-SQL-types and Time4J is done this way (using the subclass JDBCAdapter):

Objects of type Moment can be stored in the database by either using its canonical ISO-representation (preserving all details like nanosecond precision or leap seconds) or by mapping to a long number using the elapsed seconds since UNIX epoch. Or you simply convert a Moment first to java.util.Date and store the latter one.


The mapping between XML-types and Time4J is done this way (using the subclass XMLAdapter):

How to convert between java.util.Date and local types?

This conversion always requires a timezone or an offset because java.util.Date is a global type. Consequently you have to use an intermediate instance of class Moment. Example for PlainDate:

	TZID tzid = EUROPE.PARIS; // one hour ahead of UTC+00:00
	// to PlainDate
	java.util.Date jud1 = new java.util.Date(0L);
	PlainDate date1 = TemporalType.JAVA_UTIL_DATE.translate(jud1).toZonalTimestamp(tzid).getCalendarDate();
	System.out.println(date1); // output:  1970-01-01

	// from PlainDate (at midnight T00:00)
	PlainDate date2 = PlainDate.of(1970, 1, 1);
	java.util.Date jud2 = TemporalType.JAVA_UTIL_DATE.from(date2.atStartOfDay().inTimezone(tzid));
	System.out.println(jud2.getTime() + " ms"); // -3600000 ms (= 1969-12-31T23:00)

Interoperability with Java 8 (in version line 4.x)

Since version v4.0, the class TemporalType is extended by several conversion constants which help to convert between some Time4J-types and the most important types of the new built-in library java.time in Java-8 (JSR-310).

All four basic types of Time4J (that is PlainDate, PlainTime, PlainTimestamp and Moment) also offer short-cut-conversions using the methods from(...) and toTemporalAccessor(). Example:

	LocalDate input = ...;
	PlainDate date = PlainDate.from(input);
	date = date.with(PlainDate.DAY_OF_QUARTER.maximized());
	LocalDate endOfCurrentQuarterYear = date.toTemporalAccessor();

Every basic type of Time4J is also a TemporalAccessor. This enables you to use these types directly in code expressions based on java.util.Formatter. Example:

	String s = String.format(Locale.ENGLISH, "%1$tb %1$te, %1$tY", PlainDate.of(1995, MAY, 23));
	System.out.println(s); // May 23, 1995

Please also note the fact that a type like PlainDate can be directly used in the format engine of Java-8 (using its class DateTimeFormatter). However, this is less recommended because Time4J has its own more powerful format engine embedded in the i18n-module. Latter one can even directly print any TemporalAccessor as far as it is convertible. So the JSR-310-classes can easily take profit from the extra features of ChronoFormatter, for example printing historical dates, see next page.