Get GMT Time in Java
In Java, I want to get the current time in GMT.
I tried various options like this:
Date date = new Date();
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
date1 = calendar.getTime();
But the date is always is interpreted in my local time zone.
What am I doing wrong and how can I convert a java Da开发者_如何转开发te to GMT?
Odds are good you did the right stuff on the back end in getting the date, but there's nothing to indicate that you didn't take that GMT time and format it according to your machine's current locale.
final Date currentTime = new Date();
final SimpleDateFormat sdf =
new SimpleDateFormat("EEE, MMM d, yyyy hh:mm:ss a z");
// Give it to me in GMT time.
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("GMT time: " + sdf.format(currentTime));
The key is to use your own DateFormat, not the system provided one. That way you can set the DateFormat's timezone to what you wish, instead of it being set to the Locale's timezone.
I wonder why no one does this:
Calendar time = Calendar.getInstance();
time.add(Calendar.MILLISECOND, -time.getTimeZone().getOffset(time.getTimeInMillis()));
Date date = time.getTime();
Update: Since Java 8,9,10 and more, there should be better alternatives supported by Java. Thanks for your comment @humanity
From my experience, the bundled Calendar and Date classes in Java can yield undersired effect.
If you wouldn't mind upgrading to Java 8, then consider using ZonedDateTime
like so:
ZonedDateTime currentDate = ZonedDateTime.now( ZoneOffset.UTC );
tl;dr
Instant.now()
java.time
The Answer by Damilola is correct in suggesting you use the java.time framework built into Java 8 and later. But that Answer uses the ZonedDateTime
class which is overkill if you just want UTC rather than any particular time zone.
The troublesome old date-time classes are now legacy, supplanted by the java.time classes.
Instant
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).
Simple code:
Instant instant = Instant.now() ;
instant.toString(): 2016-11-29T23:18:14.604Z
You can think of Instant
as the building block to which you can add a time zone (ZoneID
) to get a ZonedDateTime
.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
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 java.time.
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?
- Java SE 8 and SE 9 and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
- See How to use….
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.
To get the time in millis at GMT all you need is
long millis = System.currentTimeMillis();
You can also do
long millis = new Date().getTime();
and
long millis =
Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis();
but these are inefficient ways of making the same call.
After trying a lot of methods, I found out, to get the time in millis at GMT you need to create two separate SimpleDateFormat
objects, one for formatting in GMT and another one for parsing.
Here is the code:
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = new Date();
SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dateTime= dateParser.parse(format.format(date));
long gmtMilliSeconds = dateTime.getTime();
This works fine. :)
You can achieve it using Java 8 java.time
package
Get current GMT time in Java:
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println("Print current time in GMT: "+zonedDateTime); // 2021-08-30T03:58:05.815942377Z
Convert a java.util.Date to GMT
// use a formatter
DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss O");
Date date = new Date(); //; java.util.Date object
Instant instant = date.toInstant();
ZonedDateTime zonedDateTime = instant.atZone(ZoneOffset.UTC);
System.out.println("java.util.Date to GMT: "+customFormatter.format(zonedDateTime)); // 08/30/2021 03:58:05 GMT
Ref
- ZonedDateTime
- DateTimeFormatter
- Instant
You can’t
First, you are asking the impossible. An old-fashioned Date
object hasn’t got, as in cannot have a time zone or GMT offset.
But the date is always is interpreted in my local time zone.
I suppose that you have printed the Date
or done something else that implicitly calls it toString
method. I believe that this is the only time that the Date
is interpreted in your time zone. More precisely in the current default time zone of your JVM. On the other hand this is unavoidable. Date.toString()
does behave in that way, it picks up the JVM’s time zone setting and uses it for rendering the string to be returned.
You can with java.time
You shouldn’t use a Date
, though. That class is poorly designed and fortunately long outdated. Also java.time, the modern Java date and time API that replaces it, has a class or two for dates and times with offset from GMT or UTC. I am considering GMT and UTC synonymous for now, strictly speaking they are not.
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println("Time now in UTC (GMT) is " + now);
When I ran this snippet just now, the output was:
Time now in UTC (GMT) is 2019-06-17T11:51:38.246188Z
The trailing Z
of the output means UTC.
Links
- Oracle tutorial: Date Time explaining how to use java.time.
- The Difference Between GMT and UTC on timeanddate.com.
This is pretty simple and straight forward.
Date date = new Date();
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
Calendar cal = Calendar.getInstance(TimeZone.getDefault());
date = cal.getTime();
Now date will contain the current GMT time.
Useful Utils methods as below for manage Time in GMT with DST Savings:
public static Date convertToGmt(Date date) {
TimeZone tz = TimeZone.getDefault();
Date ret = new Date(date.getTime() - tz.getRawOffset());
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if (tz.inDaylightTime(ret)) {
Date dstDate = new Date(ret.getTime() - tz.getDSTSavings());
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if (tz.inDaylightTime(dstDate)) {
ret = dstDate;
}
}
return ret;
}
public static Date convertFromGmt(Date date) {
TimeZone tz = TimeZone.getDefault();
Date ret = new Date(date.getTime() + tz.getRawOffset());
// if we are now in DST, back off by the delta. Note that we are checking the GMT date, this is the KEY.
if (tz.inDaylightTime(ret)) {
Date dstDate = new Date(ret.getTime() + tz.getDSTSavings());
// check to make sure we have not crossed back into standard time
// this happens when we are on the cusp of DST (7pm the day before the change for PDT)
if (tz.inDaylightTime(dstDate)) {
ret = dstDate;
}
}
return ret;
}
After java 8, you may want to get the formatted time as below:
DateTimeFormatter.ofPattern("HH:mm:ss.SSS").format(LocalTime.now(ZoneId.of("GMT")));
The following code will get the date minus timezone offset:
protected Date toGmt0(ZonedDateTime time) {
ZonedDateTime gmt0 = time.minusSeconds(time.getOffset().getTotalSeconds());
return Date.from(gmt0.toInstant());
}
@Test
public void test() {
ZonedDateTime now = ZonedDateTime.now();
Date dateAtSystemZone = Date.from(now.toInstant());
Date dateAtGmt0 = toGmt0(now);
SimpleDateFormat sdfWithoutZone = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
SimpleDateFormat sdfWithZoneGmt0 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ITALIAN);
sdfWithZoneGmt0.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(""
+ "\ndateAtSystemZone = " + dateAtSystemZone
+ "\ndateAtGmt0 = " + dateAtGmt0
+ "\ndiffInMillis = " + (dateAtSystemZone.getTime() - dateAtGmt0.getTime())
+ "\n"
+ "\ndateWithSystemZone.format = " + sdfWithoutZone.format(dateAtSystemZone)
+ "\ndateAtGmt0.format = " + sdfWithoutZone.format(dateAtGmt0)
+ "\n"
+ "\ndateFormatWithGmt0 = " + sdfWithZoneGmt0.format(dateAtSystemZone)
);
output :
dateAtSystemZone = Thu Apr 23 14:03:36 CST 2020
dateAtGmt0 = Thu Apr 23 06:03:36 CST 2020
diffInMillis = 28800000
dateWithSystemZone.format = 2020-04-23 14:03:36.140
dateAtGmt0.format = 2020-04-23 06:03:36.140
dateFormatWithGmt0 = 2020-04-23 06:03:36.140
My system is at GMT+8, so diffInMillis = 28800000 = 8 * 60 * 60 * 1000
。
精彩评论