Reputation: 151
Can I change the timezone of Date object in my java code without changing the date?
When I write
Date date = new Date(longValue);
I get this date in my local timezone. I want to get this date but my timezone should be one present in DB (not local) for my userID (for eg "America/Chicago").
Thanks in advance for your help.
Upvotes: 4
Views: 4865
Reputation: 338366
ZonedDateTime zdtMontreal =
ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
ZonedDateTime zdtAuckland =
zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );
Not the same moment. The zdtAuckland
moment occurred several hours earlier.
Be certain that is truly your intention. I have a sinking feeling you are doing the wrong thing, confused about how date-time handling works. Date-time work is confusing. Be sure to search and study Stack Overflow.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
The Local…
classes purposely have no time zone or offset-from-UTC information.
LocalDate ld = LocalDate.of( 2016 , Month.January , 23 ); // 2016-01-23
LocalTime lt = LocalTime.of( 12 , 34 , 56 ); // 12:34:56
These values do not yet represent a point on the timeline. Would that be the noon hour of Auckland NZ, Paris FR, or Montréal CA? We must apply a time zone to determine an actual moment. We apply a ZoneId
to get a ZonedDateTime
.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
or CST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId zMontreal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtMontreal = ZonedDateTime.of( ld , lt , zMontreal );
To see a string representing this value in the standard ISO 8601 format, call toString
. Actually, the ZonedDateTime
class extends the standard format by wisely appending the name of the time zone in square brackets.
String outputMontreal = zdtMontreal.toString();
2016-01-23T12:34:56-05:00[America/Montreal]
To get the same date and same time-of-day in another time zone, repeat the process.
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = ZonedDateTime.of( ld , lt , zParis );
ZoneId zAuckland = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdtAuckland = ZonedDateTime.of( ld , lt , zAuckland );
But know that you are getting a different moment in time. Noon in Auckland happens several hours before noon in Paris, and noon in Montréal is even later, for three different points in time that happen to share coincidentally the same wall-clock time.
2016-01-23T12:34:56-05:00[America/Montreal]
2016-01-23T12:34:56+01:00[Europe/Paris]
2016-01-23T12:34:56+13:00[Pacific/Auckland]
To get the current moment, call Instant.now
. 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 instance = Instance.now();
Apply a ZoneId
to adjust into a time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instance.atZone( z );
Repeat the process for other desired time zones, similar to what we did further above.
As a shortcut, you can get a ZonedDateTime
directly.
ZonedDateTime zdtMontreal = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
And as another shortcut, you can apply a different time zone while retaining the same date and same time-of-day (the same wall-clock time). Call ZonedDateTime::withZoneSameLocal
.
ZonedDateTime zdtAuckland = zdtMontreal.withZoneSameLocal( ZoneId.of( "Pacific/Auckland" ) );
I repeat: This results is different points on the time line. The zdtAuckland
is happening several hours before zdtMontreal
occurs.
To keep the same moment, instead call ZonedDateTime::withZoneSameInstant
.
Usually best to store your date-time values in a database in UTC. Already discussed extensively on Stack Overflow. Search for more info.
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?
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.
Upvotes: 14
Reputation: 3469
An example of how to do it using Java8 ZonedDateTime
class:
Date date = new Date(longValue);
ZoneId = ZoneId.of("America/Chicago");
ZonedDateTime dt = ZonedDateTime.ofInstant(date.toInstant(), zoneId);
You've tagged the question with Joda, but really with Java8 you don't need it anymore.
Upvotes: 0
Reputation: 368
You may find ZonedDateTime
quite helpful:
Java 8 Convert given time and time zone to UTC time
Alternatively you can create another Date
object and apply some offset to it manually.
Upvotes: 0