now() now() method of a ZonedDateTime class used to obtain the current date-time from the system clock in the default time-zone. This method will return ZonedDateTime based on system clock with default time-zone to obtain the current date-time. The zone and offset will be set based on the time-zone in the clock.
Changing Timezones of ZonedDateTime To convert a ZonedDateTime instance from one timezone to another, follow the two steps: Create ZonedDateTime in 1st timezone. You may already have it in your application. Convert the first ZonedDateTime in second timezone using withZoneSameInstant() method.
Using strptime() , date and time in string format can be converted to datetime type. The first parameter is the string and the second is the date time format specifier. One advantage of converting to date format is one can select the month or date or time individually.
ZonedDateTime is an immutable representation of a date-time with a time-zone. This class stores all date and time fields, to a precision of nanoseconds, and a time-zone, with a zone offset used to handle ambiguous local date-times.
You can convert ZonedDateTime to an instant, which you can use directly with Date.
Date.from(java.time.ZonedDateTime.now().toInstant());
java.util.Date.from( // Transfer the moment in UTC, truncating any microseconds or nanoseconds to milliseconds.
Instant.now() ; // Capture current moment in UTC, with resolution as fine as nanoseconds.
)
Though there was no point in that code above. Both java.util.Date
and Instant
represent a moment in UTC, always in UTC. Code above has same effect as:
new java.util.Date() // Capture current moment in UTC.
No benefit here to using ZonedDateTime
. If you already have a ZonedDateTime
, adjust to UTC by extracting a Instant
.
java.util.Date.from( // Truncates any micros/nanos.
myZonedDateTime.toInstant() // Adjust to UTC. Same moment, same point on the timeline, different wall-clock time.
)
The Answer by ssoltanid correctly addresses your specific question, how to convert a new-school java.time object (ZonedDateTime
) to an old-school java.util.Date
object. Extract the Instant
from the ZonedDateTime and pass to java.util.Date.from()
.
Note that you will suffer data loss, as Instant
tracks nanoseconds since epoch while java.util.Date
tracks milliseconds since epoch.
Your Question and comments raise other issues.
Your servers should have their host OS set to UTC as a best practice generally. The JVM picks up on this host OS setting as its default time zone, in the Java implementations that I'm aware of.
But you should never rely on the JVM’s current default time zone. Rather than pick up the host setting, a flag passed when launching a JVM can set another time zone. Even worse: Any code in any thread of any app at any moment can make a call to java.util.TimeZone::setDefault
to change that default at runtime!
Timestamp
TypeAny decent database and driver should automatically handle adjusting a passed date-time to UTC for storage. I do not use Cassandra, but it does seem to have some rudimentary support for date-time. The documentation says its Timestamp
type is a count of milliseconds from the same epoch (first moment of 1970 in UTC).
Furthermore, Cassandra accepts string inputs in the ISO 8601 standard formats. Fortunately, java.time uses ISO 8601 formats as its defaults for parsing/generating strings. The Instant
class’ toString
implementation will do nicely.
But first we need to reduce the nanosecond precision of ZonedDateTime to milliseconds. One way is to create a fresh Instant using milliseconds. Fortunately, java.time has some handy methods for converting to and from milliseconds.
Here is some example code in Java 8 Update 60.
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
…
Instant instant = zdt.toInstant();
Instant instantTruncatedToMilliseconds = Instant.ofEpochMilli( instant.toEpochMilli() );
String fodderForCassandra = instantTruncatedToMilliseconds.toString(); // Example: 2015-08-18T06:36:40.321Z
Or according to this Cassandra Java driver doc, you can pass a java.util.Date
instance (not to be confused with java.sqlDate
). So you could make a j.u.Date from that instantTruncatedToMilliseconds
in the code above.
java.util.Date dateForCassandra = java.util.Date.from( instantTruncatedToMilliseconds );
If doing this often, you could make a one-liner.
java.util.Date dateForCassandra = java.util.Date.from( zdt.toInstant() );
But it would be neater to create a little utility method.
static public java.util.Date toJavaUtilDateFromZonedDateTime ( ZonedDateTime zdt ) {
Instant instant = zdt.toInstant();
// Data-loss, going from nanosecond resolution to milliseconds.
java.util.Date utilDate = java.util.Date.from( instant ) ;
return utilDate;
}
Notice the difference in all this code than in the Question. The Question’s code was trying to adjust the time zone of the ZonedDateTime instance to UTC. But that is not necessary. Conceptually:
ZonedDateTime = Instant + ZoneId
We just extract the Instant part, which is already in UTC (basically in UTC, read the class doc for precise details).
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.
If you are using the ThreeTen backport for Android and can't use the newer Date.from(Instant instant)
(which requires minimum of API 26) you can use:
ZonedDateTime zdt = ZonedDateTime.now();
Date date = new Date(zdt.toInstant().toEpochMilli());
or:
Date date = DateTimeUtils.toDate(zdt.toInstant());
Please also read the advice in Basil Bourque's answer
Here is an example converting current system time to UTC. It involves formatting ZonedDateTime as a String and then the String object will be parsed into a date object using java.text DateFormat.
ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC);
final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
final DateFormat FORMATTER_YYYYMMDD_HH_MM_SS = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
String dateStr = zdt.format(DATETIME_FORMATTER);
Date utcDate = null;
try {
utcDate = FORMATTER_YYYYMMDD_HH_MM_SS.parse(dateStr);
}catch (ParseException ex){
ex.printStackTrace();
}
The accepted answer did not work for me. The Date returned is always the local Date and not the Date for the original Time Zone. I live in UTC+2.
//This did not work for me
Date.from(java.time.ZonedDateTime.now().toInstant());
I have come up with two alternative ways to get the correct Date from a ZonedDateTime.
Say you have this ZonedDateTime for Hawaii
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.of("US/Hawaii"); // UTC-10
or for UTC as asked originally
Instant zulu = Instant.now(); // GMT, UTC+0
ZonedDateTime zdt = zulu.atZone(ZoneId.of("UTC"));
Alternative 1
We can use java.sql.Timestamp. It is simple but it will probably also make a dent in your programming integrity
Date date1 = Timestamp.valueOf(zdt.toLocalDateTime());
Alternative 2
We create the Date from millis (answered here earlier). Note that local ZoneOffset is a must.
ZoneOffset localOffset = ZoneOffset.systemDefault().getRules().getOffset(LocalDateTime.now());
long zonedMillis = 1000L * zdt.toLocalDateTime().toEpochSecond(localOffset) + zdt.toLocalDateTime().getNano() / 1000000L;
Date date2 = new Date(zonedMillis);
For a docker application like beehuang commented you should set your timezone.
Alternatively you can use withZoneSameLocal. For example:
2014-07-01T00:00+02:00[GMT+02:00] is converted by
Date.from(zonedDateTime.withZoneSameLocal(ZoneId.systemDefault()).toInstant())
to Tue Jul 01 00:00:00 CEST 2014 and by
Date.from(zonedDateTime.toInstant())
to Mon Jun 30 22:00:00 UTC 2014
You can do this using the java.time classes built into Java 8 and later.
ZonedDateTime temporal = ...
long epochSecond = temporal.getLong(INSTANT_SECONDS);
int nanoOfSecond = temporal.get(NANO_OF_SECOND);
Date date = new Date(epochSecond * 1000 + nanoOfSecond / 1000000);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With