138

I have problems with Date class in Java. Date class returns local machine date but i need UTC-0.

I have googled and found great solution for JavaScript but for Java nothing useful.

How to get UTC+0 date in Java 8?

Jonik
  • 80,077
  • 70
  • 264
  • 372
Mark
  • 1,513
  • 2
  • 10
  • 11
  • 13
    `java.util.Date` is never a local machine date. It is always defined as elapsed millisecs since 1970-01-01 relative to UTC+00:00. Maybe the behaviour of its method `toString()` confuses you which indeed use a representation in local timezone. – Meno Hochschild Oct 01 '14 at 19:34
  • One probable answer can be found in the question: https://stackoverflow.com/questions/45350095/how-to-get-date-in-utc-0-in-java – Priya Jain Jul 27 '17 at 12:46
  • @MenoHochschild The java.util.Date is old API/ Question was about java8 time API – Oleksandr Kulychok Apr 28 '23 at 02:30
  • @OleksandrKulychok Please have a look again at the content of the old question. The OP told about problems "with Date class in Java". So it was not about java8-Time API in that year 2014. – Meno Hochschild Apr 29 '23 at 13:19

5 Answers5

249

tl;dr

Instant.now()

java.time

The troublesome old date-time classes bundled with the earliest versions of Java have been supplanted by the java.time classes built into Java 8 and later. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

Instant

An Instant represents a moment on the timeline in UTC with a resolution of up to nanoseconds.

Instant instant = Instant.now();

The toString method generates a String object with text representing the date-time value using one of the standard ISO 8601 formats.

String output = instant.toString();  

2016-06-27T19:15:25.864Z

The Instant class is a basic building-block class in java.time. This should be your go-to class when handling date-time as generally the best practice is to track, store, and exchange date-time values in UTC.

OffsetDateTime

But Instant has limitations such as no formatting options for generating strings in alternate formats. For more flexibility, convert from Instant to OffsetDateTime. Specify an offset-from-UTC. In java.time that means a ZoneOffset object. Here we want to stick with UTC (+00) so we can use the convenient constant ZoneOffset.UTC.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );

2016-06-27T19:15:25.864Z

Or skip the Instant class.

OffsetDateTime.now( ZoneOffset.UTC )

Now with an OffsetDateTime object in hand, you can use DateTimeFormatter to create String objects with text in alternate formats. Search Stack Overflow for many examples of using DateTimeFormatter.

ZonedDateTime

When you want to display wall-clock time for some particular time zone, apply a ZoneId to get a ZonedDateTime.

In this example we apply Montréal time zone. In the summer, under Daylight Saving Time (DST) nonsense, the zone has an offset of -04:00. So note how the time-of-day is four hours earlier in the output, 15 instead of 19 hours. Instant and the ZonedDateTime both represent the very same simultaneous moment, just viewed through two different lenses.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

2016-06-27T15:15:25.864-04:00[America/Montreal]

Converting

While you should avoid the old date-time classes, if you must you can convert using new methods added to the old classes. Here we use java.util.Date.from( Instant ) and java.util.Date::toInstant.

java.util.Date utilDate = java.util.Date.from( instant );

And going the other direction.

Instant instant= utilDate.toInstant();

Similarly, look for new methods added to GregorianCalendar (subclass of Calendar) to convert to and from java.time.ZonedDateTime.

Table of types of date-time classes in modern java.time versus legacy.

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.

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

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

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. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 4
    Appreciate for saying DST is a non-sense :-) – prash Feb 21 '18 at 08:57
  • so if DST didn't exist ```ZonedDateTime``` wouldn't be needed right since all ```ZoneId``` would map to one ```ZoneOffset``` we could just use ```OffsetDateTime```? – wilmol Aug 12 '19 at 01:50
  • 1
    @wilmol No. Daylight Saving Time (DST) is only one of many reasons why politicians choose to redefine the time zone boundaries and offsets within those zones. Recently North Korea changed their clock a half-hour to sync with South Korea for diplomatic reasons. In war, the invaders/occupiers may change the offset to match that of the home country. Currently there is a new fad where governments are choosing to stop DST changes but are staying permanently *on* DST rather than revert to their previous standard time. Always plan on offset of every zone changing or your app will eventually break. – Basil Bourque Aug 12 '19 at 03:48
  • 3
    Fantastic answer! I really appreciate the time you put into this. :) – drognisep Sep 04 '19 at 21:09
  • 2
    ZoneId.of( "America/Montreal" ); why would someone invent such thing in jdk? it is ugly, disgusting, not telling if there is anything wrong until run-time, who can remember all those hard code? why not impl it in ENUM class? – http8086 Jun 28 '20 at 10:27
  • 1
    @workplaylifecycle Enum objects must be known at compile time. **Politicians change the time zones** of their jurisdiction with surprising frequency. So time zone definitions, the *tzdata*, must be kept outside the JVM’s executable. That way sysadmins can update the time zone data manually without waiting for their Java implementation provider to release a new Java update. Every Java implementation update does carry a fresh *tzdata*. But when those pesky politicians get busy changing a zone relevant to you, you will need to swap out with the latest *tzdata* file. So, an enum is not a solution. – Basil Bourque Jun 28 '20 at 16:52
  • True, I think there are such environments definitely, and it is OK to `kept outside the JVM during run-time`, I have no doubt with this point. but there are also such environments which has no requirement of `changing time zones`, yes, sounds strange, but it is the truth. so, I think it would be very nice to have Enum of time zone at compile-time and supporting dynamic time zone config at run-time. – http8086 Jun 29 '20 at 07:45
  • @workplaylifecycle If you care about time zones, how could you not care about changes to the rules defined within those time zones? For example, if your time zone was scheduled to go off of Daylight Saving Time (DST) later in the year on November 1 (“Fall back”) but your politicians suddenly decide to cancel that event and instead stay on DST year round, then your existing tzdata will be wrong by an hour for any date in the future after November 1. This example is not fiction, by the way. – Basil Bourque Jun 29 '20 at 08:43
165

With Java 8 you can write:

OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);

To answer your comment, you can then convert it to a Date (unless you depend on legacy code I don't see any reason why) or to millis since the epochs:

Date date = Date.from(utc.toInstant());
long epochMillis = utc.toInstant().toEpochMilli();
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    thanks. it is possible convert ZonedDateTime to Date or to long (ms) ? – Mark Oct 01 '14 at 14:11
  • 8
    While this Answer’s code technically works, wouldn’t it be more appropriate to use `OffsetDateTime` rather than `ZonedDateTime` given that we are working with a mere offset-from-UTC rather than a full time zone? – Basil Bourque Jun 27 '16 at 19:25
  • 1
    Wouldn't `utc.toInstant().toEpochMilli()` be a more precise conversion to millis? – iwat0qs Aug 23 '20 at 10:43
7

In java8, I would use the Instant class which is already in UTC and is convenient to work with.

import java.time.Instant;

Instant ins = Instant.now();
long ts = ins.toEpochMilli();

Instant ins2 = Instant.ofEpochMilli(ts)

Alternatively, you can use the following:

import java.time.*;

Instant ins = Instant.now(); 

OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);
ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));

Back to Instant

Instant ins4 = Instant.from(odt);
Abel Terefe
  • 1,440
  • 20
  • 17
  • 5
    No, an [`Instant`](http://docs.oracle.com/javase/8/docs/api/java/time/Instant.html) is *not* at local time. An `Instant` by definition is in UTC. So no need for the machinations seen in this Answer trying to get into UTC; the `Instant` already *is* in UTC. See [my Answer](http://stackoverflow.com/a/38061562/642706) for more info and much simpler code. – Basil Bourque Jun 27 '16 at 19:19
3

In Java8 you use the new Time API, and convert an Instant in to a ZonedDateTime Using the UTC TimeZone

rolfl
  • 17,539
  • 7
  • 42
  • 76
3

I did this in my project and it works like a charm

Date now = new Date();
System.out.println(now);
TimeZone.setDefault(TimeZone.getTimeZone("UTC")); // The magic is here
System.out.println(now);
Federico Traiman
  • 1,191
  • 1
  • 13
  • 18