117

I need to force any time related operations to GMT/UTC, regardless the timezone set on the machine. Any convenient way to so in code?

To clarify, I'm using the DB server time for all operations, but it comes out formatted according to local timezone.

Thanks!

SyBer
  • 5,407
  • 13
  • 55
  • 64

13 Answers13

144

The OP answered this question to change the default timezone for a single instance of a running JVM, set the user.timezone system property:

java -Duser.timezone=GMT ... <main-class>

If you need to set specific time zones when retrieving Date/Time/Timestamp objects from a database ResultSet, use the second form of the getXXX methods that takes a Calendar object:

Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
ResultSet rs = ...;
while (rs.next()) {
    Date dateValue = rs.getDate("DateColumn", tzCal);
    // Other fields and calculations
}

Or, setting the date in a PreparedStatement:

Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
PreparedStatement ps = conn.createPreparedStatement("update ...");
ps.setDate("DateColumn", dateValue, tzCal);
// Other assignments
ps.executeUpdate();

These will ensure that the value stored in the database is consistent when the database column does not keep timezone information.

The java.util.Date and java.sql.Date classes store the actual time (milliseconds) in UTC. To format these on output to another timezone, use SimpleDateFormat. You can also associate a timezone with the value using a Calendar object:

TimeZone tz = TimeZone.getTimeZone("<local-time-zone>");
//...
Date dateValue = rs.getDate("DateColumn");
Calendar calValue = Calendar.getInstance(tz);
calValue.setTime(dateValue);

Usefull Reference

https://docs.oracle.com/javase/9/troubleshoot/time-zone-settings-jre.htm#JSTGD377

https://confluence.atlassian.com/kb/setting-the-timezone-for-the-java-environment-841187402.html

shareef
  • 9,255
  • 13
  • 58
  • 89
Kevin Brock
  • 8,874
  • 1
  • 33
  • 37
  • 2
    One thing to note about setting the timezone for the entire JVM is that it affects everything, including such things as logging. Just something to keep in mind if that's the desired effect. – Hermann Hans Apr 13 '10 at 10:16
  • Yep, that fine. Just one point to mention, that I actually set the user.timezone directly in code, rather then via the -D parameter. – SyBer Apr 13 '10 at 21:10
  • 6
    @SyBer: That works but you must ensure that you set this before any method calls the TimeZone.getDefault() method. If not you will have some confusion since the default is cached after the first execution. This also means it could be a problem if you do this inside an API/library (hidden from plain view) - be sure to document heavily what you are doing. – Kevin Brock Apr 14 '10 at 00:24
25

Also if you can set JVM timezone this way

System.setProperty("user.timezone", "EST");

or -Duser.timezone=GMT in the JVM args.

Silviu Burcea
  • 5,103
  • 1
  • 29
  • 43
MG Developer
  • 859
  • 11
  • 17
21

You could change the timezone using TimeZone.setDefault():

TimeZone.setDefault(TimeZone.getTimeZone("GMT"))
snorbi
  • 2,590
  • 26
  • 36
  • No offence, but modifying temporarily a global static state sounds like a very bad idea... – G. Demecki Jun 21 '17 at 13:56
  • 1
    You could, but you shouldn't. This is extraordinarily bad advice. The entire JVM has its timezone changed. – scot Jan 24 '19 at 13:17
  • 5
    Sometimes it is exactly what you want to achieve. Eg. I have seen Java-based microservices running always with UTC to avoid time zone problems. In these systems the database backend runs with UTC as well, so it is natural to "force" the JVM to UTC as well. What is important: you have to know what you are doing and what are the consequences... – snorbi Jan 24 '19 at 13:27
  • 1
    absolutely not. If you want your entire system in UTC (a very good idea), set the system timezone to UTC and leave the Java timezone alone. – scot Feb 24 '19 at 03:25
  • 10
    Except if you have multiple JVMs with different requirements. We can argue forever but every case is unique: sometimes you need to set the entire system's timezone, sometimes you set only one JVM's. Let's be happy that today's systems are so flexible that we can do both – snorbi Feb 24 '19 at 08:50
13

I had to set the JVM timezone for Windows 2003 Server because it always returned GMT for new Date();

-Duser.timezone=America/Los_Angeles

Or your appropriate time zone. Finding a list of time zones proved to be a bit challenging also...

Here are two list;

http://wrapper.tanukisoftware.com/doc/english/prop-timezone.html

http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzatz%2F51%2Fadmin%2Freftz.htm

Doug Porter
  • 7,721
  • 4
  • 40
  • 55
Todd
  • 131
  • 1
  • 2
12

tl;dr

String sql = "SELECT CURRENT_TIMESTAMP ;
…
OffsetDateTime odt = myResultSet.getObject( 1 , OffsetDateTime.class ) ;

Avoid depending on host OS or JVM for default time zone

I recommend you write all your code to explicitly state the desired/expected time zone. You need not depend on the JVM’s current default time zone. And be aware that the JVM’s current default time zone can change at any moment during runtime, with any code in any thread of any app calling TimeZone.setDefault. Such a call affects all apps within that JVM immediately.

java.time

Some of the other Answers were correct, but are now outmoded. The terrible date-time classes bundled with the earliest versions of Java were flawed, written by people who did not understand the complexities and subtleties of date-time handling.

The legacy date-time classes have been supplanted by the java.time classes defined in JSR 310.

To represent a time zone, use ZoneId. To represent an offset-from-UTC, use ZoneOffset. An offset is merely a number of hour-minutes-seconds ahead or behind the prime meridian. A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region.

I need to force any time related operations to GMT/UTC

For an offset of zero hours-minutes-seconds, use the constant ZoneOffset.UTC.

Instant

To capture the current moment in UTC, use an Instant. This class represent a moment in UTC, always in UTC by definition.

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

ZonedDateTime

To see that same moment through the wall-clock time used by the people of a particular region, adjust into a time zone. Same moment, same point on the timeline, different wall-clock time.

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Database

You mention a database.

To retrieve a moment from the database, your column should be of a data type akin to the SQL-standard TIMESTAMP WITH TIME ZONE. Retrieve an object rather than a string. In JDBC 4.2 and later, we can exchange java.time objects with the database. The OffsetDateTime is required by JDBC, while Instant & ZonedDateTime are optional.

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

In most databases and drivers, I would guess that you will get the moment as seen in UTC. But if not, you can adjust in either of two ways:

  • Extract a Instant: odt.toInstant()
  • Adjust from the given offset to an offset of zero: OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;`.

Table of date-time types in Java (both legacy and modern) and in standard SQL


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.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
8

for me, just quick SimpleDateFormat,

  private static final SimpleDateFormat GMT = new SimpleDateFormat("yyyy-MM-dd");
  private static final SimpleDateFormat SYD = new SimpleDateFormat("yyyy-MM-dd");
  static {
      GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
    SYD.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
  }

then format the date with different timezone.

Paul
  • 19,704
  • 14
  • 78
  • 96
Jackie
  • 25,199
  • 6
  • 33
  • 24
8

Use system property:

-Duser.timezone=UTC
Dawid Stępień
  • 1,357
  • 1
  • 9
  • 6
6

I would retrieve the time from the DB in a raw form (long timestamp or java's Date), and then use SimpleDateFormat to format it, or Calendar to manipulate it. In both cases you should set the timezone of the objects before using it.

See SimpleDateFormat.setTimeZone(..) and Calendar.setTimeZone(..) for details

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Eyal Schneider
  • 22,166
  • 5
  • 47
  • 78
1

create a pair of client / server, so that after the execution, client server sends the correct time and date. Then, the client asks the server pm GMT and the server sends back the answer right.

bertan
  • 11
  • 1
1

Execute this line in MySQL to reset your timezone:

SET @@global.time_zone = '+00:00';
Marek Puchalski
  • 3,286
  • 2
  • 26
  • 35
Saeed
  • 11
  • 1
1

Hope below code will help you.

    DateFormat formatDate = new SimpleDateFormat(ISO_DATE_TIME_PATTERN);
    formatDate.setTimeZone(TimeZone.getTimeZone("UTC")); 
    formatDate.parse(dateString);
0

Wow. I know this is an ancient thread but all I can say is do not call TimeZone.setDefault() in any user-level code. This always sets the Timezone for the whole JVM and is nearly always a very bad idea. Learn to use the joda.time library or the new DateTime class in Java 8 which is very similar to the joda.time library.

scot
  • 1,194
  • 14
  • 26
  • I use it for tests. I never know what timezone my teammates have on their computers or what's going to be set on the CI. – Auras Mar 15 '21 at 10:26
-6

If you would like to get GMT time only with intiger: var currentTime = new Date(); var currentYear ='2010' var currentMonth = 10; var currentDay ='30' var currentHours ='20' var currentMinutes ='20' var currentSeconds ='00' var currentMilliseconds ='00'

currentTime.setFullYear(currentYear);
currentTime.setMonth((currentMonth-1)); //0is January
currentTime.setDate(currentDay);  
currentTime.setHours(currentHours);
currentTime.setMinutes(currentMinutes);
currentTime.setSeconds(currentSeconds);
currentTime.setMilliseconds(currentMilliseconds);

var currentTimezone = currentTime.getTimezoneOffset();
currentTimezone = (currentTimezone/60) * -1;
var gmt ="";
if (currentTimezone !== 0) {
  gmt += currentTimezone > 0 ? ' +' : ' ';
  gmt += currentTimezone;
}
alert(gmt)
Incmos
  • 1