Java Convert Gmt/Utc to Local Time Doesn't Work as Expected

Java Convert GMT/UTC to Local time doesn't work as expected

I also recommend using Joda as mentioned before.

Solving your problem using standard Java Date objects only can be done as follows:

    // **** YOUR CODE **** BEGIN ****
long ts = System.currentTimeMillis();
Date localTime = new Date(ts);
String format = "yyyy/MM/dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(format);

// Convert Local Time to UTC (Works Fine)
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Date gmtTime = new Date(sdf.format(localTime));
System.out.println("Local:" + localTime.toString() + "," + localTime.getTime() + " --> UTC time:"
+ gmtTime.toString() + "," + gmtTime.getTime());

// **** YOUR CODE **** END ****

// Convert UTC to Local Time
Date fromGmt = new Date(gmtTime.getTime() + TimeZone.getDefault().getOffset(localTime.getTime()));
System.out.println("UTC time:" + gmtTime.toString() + "," + gmtTime.getTime() + " --> Local:"
+ fromGmt.toString() + "-" + fromGmt.getTime());

Output:

Local:Tue Oct 15 12:19:40 CEST 2013,1381832380522 --> UTC time:Tue Oct 15 10:19:40 CEST 2013,1381825180000
UTC time:Tue Oct 15 10:19:40 CEST 2013,1381825180000 --> Local:Tue Oct 15 12:19:40 CEST 2013-1381832380000

How can I get the current date and time in UTC or GMT in Java?

java.util.Date has no specific time zone, although its value is most commonly thought of in relation to UTC. What makes you think it's in local time?

To be precise: the value within a java.util.Date is the number of milliseconds since the Unix epoch, which occurred at midnight January 1st 1970, UTC. The same epoch could also be described in other time zones, but the traditional description is in terms of UTC. As it's a number of milliseconds since a fixed epoch, the value within java.util.Date is the same around the world at any particular instant, regardless of local time zone.

I suspect the problem is that you're displaying it via an instance of Calendar which uses the local timezone, or possibly using Date.toString() which also uses the local timezone, or a SimpleDateFormat instance, which, by default, also uses local timezone.

If this isn't the problem, please post some sample code.

I would, however, recommend that you use Joda-Time anyway, which offers a much clearer API.

How to convert an offset from GMT to the local timezone?

(If you don't want to use JodaTime) Use TimeZone with setRawOffset with code from this answer: https://stackoverflow.com/a/19378721/360211

Convert UTC date to current timezone

it print GMT+02 because this is your "local" timezone.
if you want to print the date without timezone information, use SimpleDateFormat to format the date to you liking.

edit : adding the code example (with your variable 'myDate')

SimpleDateFormat inputSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
inputSDF.setTimeZone(TimeZone.getTimeZone("UTC"));
Date myDate = inputSDF.parse("2016-09-25 17:26:12");
//
SimpleDateFormat outputSDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(outputSDF.format(myDate));
System.out.println(TimeZone.getDefault().getID());

yield on the (my) console (with my local timezone).

2016-09-25 19:26:12
Europe/Paris

Converting time to UTC time goes the opposite way

tl;dr

Use modern java.time classes. Convert to legacy class only if necessary to work with old code.

Specifically, parse your input string as a OffsetDateTime object, adjust to UTC by extracting an Instant, and lastly, convert to java.sql.Timestamp (only if you must).

java.sql.Timestamp ts =                           // Avoid using this badly-designed legacy class if at all possible.
Timestamp // You can convert back-and-forth between legacy and modern classes.
.from( // New method added to legacy class to convert from modern class.
OffsetDateTime // Represents a moment with an offset-of-UTC, a number of some hours-minutes-seconds ahead or behind UTC.
.parse( "2019-01-22T13:09:54.620-05:00" ) // Text in standard ISO 8601 format can be parsed by default, without a formatting pattern.
.toInstant() // Adjust from an offset to UTC (an offset of zero) by extracting an `Instant`.
) // Returns a `Timestamp` object. Same moment as both the `OffsetDateTime` and `Instant` objects.
;

See this code run live at IdeOne.com, resulting in:

ts.toString(): 2019-01-22 18:09:54.62

If using JDBC 4.2 or later, skip the Timestamp altogether.

myPreparedStatement.setObject( … , myOffsetDateTime ) ;

Zulu

2019-01-22T13:09:54.620-05:00 should be --> 2019-01-22T18:09:54.620

If you meant that second value to represent a moment in UTC, append the offset-from-UTC to indicate that fact. Either +00:00 or Z (pronounced “Zulu”): 2019-01-22T18:09:54.620Z.

Reporting a moment without an offset-from-UTC or time zone indicator is like reporting an amount of money without a currency indicator.

OffsetDateTime

A string with an offset-from-UTC should be parsed as a OffsetDateTime object.

Your input string happens to comply with the ISO 8601 standard formats for textual date-time values. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.

OffsetDateTime odt = OffsetDateTime.parse( "2019-01-22T13:09:54.620-05:00" ) ;

Timestamp

Apparently you want a java.sql.Timestamp object. This is one of the terrible date-time classes bundled with the earliest versions of Java. These classes are now legacy, supplanted entirely by the modern java.time classes with the adoption of JSR 310. Avoid these legacy classes whenever possible.

If you must have a Timestamp to interoperate with old code not yet updated to work with java.time, you can convert. To convert, call new methods added to the old classes.

Instant

The java.sql.Timestamp class carries a from( Instant ) method. An Instant is a moment in UTC. To adjust from the offset of our OffsetDateTime to UTC, just extract an Instant.

Instant instant = odt.toInstant() ;
java.sql.Timestamp ts = Timestamp.from( instant ) ;

We have three objects ( odt, instant, & ts ) that all represent the same moment. The first has a different wall-clock time. But all three are the same simultaneous point on the timeline.

JDBC 4.2

As of JDBC 4.2, we can directly exchange java.time objects with the database. So no need to use Timestamp.

myPreparedStatement.setObject( … , odt ) ;

…and…

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

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.

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?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - 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
    • Most 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 (<26), 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.



Related Topics



Leave a reply



Submit