开发者

Java time in GMT

I have a Grails application with the following code:

Date now = Calendar.getInstance().getTime() //Also tried new Date()
println "now: " + now

When I do this, I get now: Thu Aug 18 12:47:09 CDT 2011. I need the date to be in GMT, not local time because I need to store the GMT time in a database. I can use a simpleDateFormat object to print out the time in GMT, but I need to actually store it as GMT.

Question: 开发者_运维百科How do I convert a Date object to a Date object using GMT?


This accentuates why Java sucks at time. The previous posts are all close, but we need to be very careful about getting the current time in GMT, and getting the current time in CDT and calling it GMT.

TimeZone reference = TimeZone.getTimeZone("GMT");
Calendar myCal = Calendar.getInstance(reference);

This is the current time in GMT, with a timezone context of GMT.

To convert to a Date object which keeps the zone intact you'll need to call:

TimeZone.setDefault(reference);

This setting will last as long as your current JVM. Now calling get Time should produce the desired result.

myCal.getTime();


Well, if you really want time in GMT, you need to get it as GMT (@jpredham is right. Kudos to you! Editing my post to reflect this)

So do the following

//this option uses TimeZone
TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");
TimeZone.setDefault(gmtTimeZone);
Calendar calendar = Calender.getInstance(gmtTimeZone);

Date myDate = calendar.getTime();


Try this:

println Calendar.getInstance(TimeZone.getTimeZone('GMT')).format('HH:mm:ss')

Note that when you convert to a date, you lose the timezone information. When Java/Groovy formats your Date for printing, it automatically formats it for your local timezone. Don't worry, your date doesn't have a timezone associated with it. You can add the proper timezone back in when you display it like so:

Date now = Calendar.getInstance(TimeZone.getTimeZone('GMT')).time
def formatter = new java.text.SimpleDateFormat('HH:mm:ss')
formatter.timeZone = TimeZone.getTimeZone('GMT')
println formatter.format(now)


Internally a Calendar object stores the time in UTC (the modern name for GMT). getTimeInMillis() returns a UTC value, and is probably what you want to store.


You should try GregorianCalendar#setTimeZone(TimeZone timeZone).


Using System.currentTimeMillis() is not only much faster than using Calendar or Date, it always gives you the GMT time. If you want to display this time, you can use SimpleDateFormat, setting the time zone to what ever you want.


You are confusing date-time object with its string representation. All common date-time libraries in Java (java.util.Date, Joda-Time, java.time in Java 8) internally track a fractional number of seconds since the first moment of 1970 in UTC while ignoring leap seconds. So in all three libraries, the date-time is internally always in UTC/GMT.

So your question of how to convert a Date object to a Date object in GMT (UTC) makes no sense.

The two better libraries (Joda-Time and java.time) also track a time zone inside the date-time object. The notoriously troublesome java.util.Date has no time zone assigned yet confusingly applies the JVM's current default time zone when it's toString method is invoked.

For the record, Joda-Time makes short work of this.

DateTime nowUtc = DateTime.now( DateTimeZone.UTC );

Calling that object's toString method generates a string in ISO 8601 format in Zulu (UTC) time.

Search StackOverflow for "Joda" and "formatter" to find many examples of adjusting to other time zones.


tl;dr

Instant.now()    // Capture current moment in UTC.
    .toString()  // Generate a String object in standard ISO 8601 format, YYYY-MM-DDTHH:MM:SS.SSSSSSSSSZ.

2018-02-16T23:28:01.101324Z

java.time

The modern approach uses java.time classes. Avoid the troublesome legacy date-time classes entirely.

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).

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Generate a string in standard ISO 8601 format by calling toString.

String output = instant.toString() ;

If you need more flexibility than Instant provides, such as formatting while generating strings, use OffsetDateTime with the constant ZoneOffset.UTC.

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;  // Capture the current moment in UTC.

To generate strings in non-standard formats, use a DateTimeFormatter.


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.

Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java 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 Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜