How to Set Time Zone of a Java.Util.Date

How to set time zone of a java.util.Date?

Use DateFormat. For example,

SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = isoFormat.parse("2010-05-23T09:01:02");

Is java.util.Date using TimeZone?

How about some pedantic detail.

java.util.Date is timezone-independent. Says so right in the javadoc.

You want something with respect to a particular timezone? That's java.util.Calendar.

The tricky part? When you print this stuff (with java.text.DateFormat or a subclass), that involves a Calendar (which involves a timezone). See DateFormat.setTimeZone().

It sure looks (haven't checked the implementation) like java.util.Date.toString() goes through a DateFormat. So even our (mostly) timezone-independent class gets messed up w/ timezones.

Want to get that timezone stuff out of our pure zoneless Date objects? There's Date.toGMTString(). Or you can create your own SimpleDateFormatter and use setTimeZone() to control which zone is used yourself.

How to change the timezone offset in Java for a Date object?

I have a Date object that is getting the date from the database which is already in UTC,

Don’t.

The terrible Date class was supplanted years ago by the modern java.time classes.

You should be retrieving a moment from a database column of type TIMESTAMP WITH TIME ZONE by using OffsetDateTime.

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

That value is likely to be in UTC. If you want to view that moment adjusted into a time zone, apply a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

but the timezone offset gets converted based on the location where the application is running.

Be aware that while a java.util.Date is actually a moment in UTC, its toString method tells a lie. That method dynamically applies the JVM’s current default time zone while generating its text. While well-intentioned, this anti-feature creates the illusion of a time zone being present inside the Date.

No such problem if you use the java.time classes only. There is no need to ever again use java.util.Date, java.sql.Date, Calendar, GregorianCalendar, SimpleDateFormat, DateFormat, or other such legacy classes.

So if the database has date: 2019-09-06 00:00:00.000 and the application is running in LA, the Date object will have the offset of 7 and the output will look like this 2019-09-06T07:00Z

This part makes no sense to me.

Do you have the correct data types in your database? The TIMESTAMP WITHOUT TIME ZONE would be the wrong type to track a moment. This type has only a date and a time-of-day, but lacks the context of an offset-from-UTC or a time zone. This type cannot represent a specific point on the timeline.

Edit your Question to specify exactly what database and what data types are your columns.

At least try using the java.time to eliminate the confusion of Date::toString injecting an inappropriate time zone.

The Date class does not have a setTimeZone() method

A java.util.Date is always in UTC, just a count of milliseconds since the first moment of 1970 in UTC, 1970-01-01T00:00:00Z. Nothing more. (Actually there is more, a time zone buried deep, with no getter methods, that affects behavior of equals and such, but in irrelevant to our discussion here. This class is a bloody mess of bad design.)

and the first thing that came to mind is to convert it to a String and hardcode 00:00Z at the end, which isn't clean. Any ideas?

No, you definitely should not play such games. You will only get deeper into trouble. Get your data types straight in your database, use only the java.time classes in Java, and your problems will be solved.

I cannot give further help since you did not provide enough details. Search Stack Overflow to learn more. This topic has been addressed many many times already.

Convert Date/Time for given Timezone - java

For me, the simplest way to do that is:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");

//Here you say to java the initial timezone. This is the secret
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//Will print in UTC
System.out.println(sdf.format(calendar.getTime()));

//Here you set to your timezone
sdf.setTimeZone(TimeZone.getDefault());
//Will print on your default Timezone
System.out.println(sdf.format(calendar.getTime()));

How to change TIMEZONE for a java.util.Calendar/Date

In Java, Dates are internally represented in UTC milliseconds since the epoch (so timezones are not taken into account, that's why you get the same results, as getTime() gives you the mentioned milliseconds).

In your solution:

Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
long gmtTime = cSchedStartCal.getTime().getTime();

long timezoneAlteredTime = gmtTime + TimeZone.getTimeZone("Asia/Calcutta").getRawOffset();
Calendar cSchedStartCal1 = Calendar.getInstance(TimeZone.getTimeZone("Asia/Calcutta"));
cSchedStartCal1.setTimeInMillis(timezoneAlteredTime);

you just add the offset from GMT to the specified timezone ("Asia/Calcutta" in your example) in milliseconds, so this should work fine.

Another possible solution would be to utilise the static fields of the Calendar class:

//instantiates a calendar using the current time in the specified timezone
Calendar cSchedStartCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
//change the timezone
cSchedStartCal.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
//get the current hour of the day in the new timezone
cSchedStartCal.get(Calendar.HOUR_OF_DAY);

Refer to stackoverflow.com/questions/7695859/ for a more in-depth explanation.

Java.util.date get the actual date at client timezone

java.util.Date does not store any time zone. It just stores the number of milliseconds since the 'epoch', which is 1 January 1970, 00:00:00 UTC.

Thus, all you have to do is to know the time zone of your server machine, find the period between this time zone and the time zone you want to convert it to and add or subtract the period.

UPDATE:

int clientGMT = 4; //GMT you want to convert to
int serverGMT = 2; //server's GMT
int delta = clientGMT - serverGMT; //delta between the dates

//assume this is the date in GMT + 2 received from the server
Date d1 = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss").parse("12.03.2019 13:00:00");

//... and you want to convert it to GMT + 4 (client side's time zone)
Date resultDate = new Date(d1.getTime() + delta * 3600000);

P.S. Yes, you have to manipulate time zones manually, as I said above, java.util.Date does not store this information (each date is assumed to be in UTC).

How do I set timezone on a specific date?

Avoid java.util.Date

A java.util.Date represents a moment in UTC. No need to manipulate it as text. Beware: the method Date::toString tells a lie, dynamically applying the JVM’s current default time zone while generating the text.

Instead, use java.time.Instant

First convert from that terrible legacy class to its modern replacement, java.time.Instant. Notice the new conversion methods added to the old classes.

Instant instant = myDate.toInstant() ;

ZonedDateTime

An Instant is also a moment in UTC. To see that same moment through the offset-from-UTC used by the people of a certain region, apply a ZoneId to get a ZonedDateTime object.

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

Be clear: This zdt object and this instant object both represent the same moment, the same point on the timeline. They are different only in the wall-clock time. Imagine someone in Iceland (always in UTC) calling someone in Québec, and they both look up at the clock on their respective walls.

Converting from modern to legacy

If you have a ZonedDateTime object in hand, and you must get a java.util.Date for interoperating with old code not yet updated to java.time, you can convert. Go from an Instant to a Date, by extracting a Instant from your ZonedDateTime object.

Instant instant = zdt.toInstant() ;
java.util.Date date = java.util.Date.from ( instant ) ;

If you need a Calendar rather than Date, the conversion is more direct.

Calendar cal = GregorianCalendar.from( zdt ) ;

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?

  • 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….

Table of which java.time library to use with which version of Java or Android

How to get the current date and time of your timezone in Java?

Date is always UTC-based... or time-zone neutral, depending on how you want to view it. A Date only represents a point in time; it is independent of time zone, just a number of milliseconds since the Unix epoch. There's no notion of a "local instance of Date." Use Date in conjunction with Calendar and/or TimeZone.getDefault() to use a "local" time zone. Use TimeZone.getTimeZone("Europe/Madrid") to get the Madrid time zone.

... or use Joda Time, which tends to make the whole thing clearer, IMO. In Joda Time you'd use a DateTime value, which is an instant in time in a particular calendar system and time zone.

In Java 8 you'd use java.time.ZonedDateTime, which is the Java 8 equivalent of Joda Time's DateTime.



Related Topics



Leave a reply



Submit