Abhinav
Abhinav

Reputation: 3438

In joda time how to convert time zone without changing time

I am getting UTC timestamp from database which is I am setting into a JodaTime DateTime instance

DateTime dt = new DateTime(timestamp.getTime());

It stores the time perfectly say 10:00 AM but with local time zone. E.g, I am in IST time zone which is +5:30 from UTC

I have tried lots of things for changing the timezone but with every thing it changes the time from 10:00 AM to something else by using +5:30 difference

Is there any way by which I can change TimeZone without affecting current time

EDIT: If my current time is:

2013-09-25 11:27:34 AM      UTC

Following is the result when I use this new DateTime(timestamp.getTime());

2013-09-25 11:27:34 AM  Asia/Kolkata

And following is the result when I use this new DateTime(timestamp.getTime(), DateTimeZone.UTC);

2013-09-25 05:57:34 AM  UTC

Upvotes: 61

Views: 71647

Answers (7)

nogridbag
nogridbag

Reputation: 3703

None of the given answers actually explained the problem. The real problem is the initial assumptions were incorrect. The timestamp from the database was created using the local JVM timezone Asia/Kolkata and not UTC. This is the default behavior with JDBC which is why it's still recommended to set your JVM timezone to UTC.

If the timestamp from the database were in fact:

2013-09-25 11:27:34 AM UTC

Or in ISO-8601 format:

2013-09-25T11:27:34Z // The trailing 'Z' means UTC

Then using the new DateTime(timestamp, DateTimeZone.UTC) constructor works fine. See for yourself:

Timestamp timestamp = new Timestamp(1380108454000L);
DateTime dt = new DateTime(timestamp.getTime(), DateTimeZone.UTC);
System.out.println(dt); // => 2013-09-25T11:27:34.000Z

If you're wondering how I got 1380108454000L, I simply used the Joda parsing classes:

ISODateTimeFormat.dateTimeParser().parseMillis("2013-09-25T11:27:34Z")

Alternatively there are websites online where you can enter a date, time, and timezone and it returns the epoch value in milliseconds or vice versa. It's sometimes good as a sanity check.

// https://www.epochconverter.com
Input: 1380108454000  Click: "Timestamp to Human Date"
Assuming that this timestamp is in milliseconds:
GMT: Wednesday, September 25, 2013 11:27:34 AM

Also, keep in mind the java.sql.Timestamp class roughly correlates to the Joda/Java 8+ Instant class. Sometimes it's easier to convert between equivalent classes to spot bugs like this earlier.

Upvotes: 3

Ben Weaver
Ben Weaver

Reputation: 970

I had the same problem. After reading this set of useful answers, and given my particular needs and available objects, I solved it by using another DateTime constructor:

new DateTime("2012-04-23T18:25:46.511Z", DateTimeZone.UTC)

Upvotes: 1

leonardo derks
leonardo derks

Reputation: 1

Also i have another approach that was very helpful for me. I wanted to have my workflow thread temporary changed to an specific Timezone (conserving the time), and then when my code finishes, i set the original timezone again. It turns out that when you are using joda libraries, doing:

TimeZone.setDefault(TimeZone.getTimeZone(myTempTimeZone));
TimeZone.setDefault(timeZone);

It's not enough. We also need to change the TimeZone in DateTimeZone as follows:

@Before
public void setUp() throws Exception {
    timeZone = TimeZone.getDefault();
    dateTimeZone = DateTimeZone.getDefault();
}

@After
public void tearDown() throws Exception {
    TimeZone.setDefault(timeZone);
    DateTimeZone.setDefault(dateTimeZone);
}

@Test
public void myTest() throws Exception {
    TimeZone.setDefault(TimeZone.getTimeZone(myTempTimeZone));
    DateTimeZone.setDefault(DateTimeZone.forID(myTempTimeZone));
    //TODO
    // my code with an specific timezone conserving time
}

Hope it helps to somebody else as well.

Upvotes: 0

StvnBrkdll
StvnBrkdll

Reputation: 4044

If your timestamp is: 2015-01-01T00:00:00.000-0500 (this is local time [for me])

Try this:

DateTime localDt = new DateTime(timestamp.getTime())
    .withZoneRetainFields(DateTimeZone.UTC)
    .withZone(DateTimeZone.getDefault());

2014-12-31T19:00:00.000-05:00

Breaking it down: This gives you a DateTime corresponding to your timestamp, specifying that it is in UTC:

new DateTime(timestamp.getTime())
    .withZoneRetainFields(DateTimeZone.UTC)

2015-01-01T00:00:00.000Z

This gives you a DateTime but with the time converted to your local time:

new DateTime(timestamp.getTime())
    .withZoneRetainFields(DateTimeZone.UTC)
    .withZone(DateTimeZone.getDefault());

2014-12-31T19:00:00.000-05:00

Upvotes: 15

Robert
Robert

Reputation: 1710

Here's how I do it:

private DateTime convertLocalToUTC(DateTime eventDateTime) {

        // get your local timezone
        DateTimeZone localTZ = DateTimeZone.getDefault();

        // convert the input local datetime to utc  
        long eventMillsInUTCTimeZone = localTZ.convertLocalToUTC(eventDateTime.getMillis(), false);

        DateTime evenDateTimeInUTCTimeZone = new DateTime(eventMillsInUTCTimeZone);

        return evenDateTimeInUTCTimeZone.toDate();
}

Upvotes: 2

user1596371
user1596371

Reputation:

You can use the withZoneRetainFields() method of DateTime to alter the timezone without altering the numerals in the date.

Upvotes: 49

Ilya
Ilya

Reputation: 29703

You can use class LocalDateTime

LocalDateTime dt = new LocalDateTime(t.getTime()); 

and convert LocalDateTime to DateTime

DateTime dt = new LocalDateTime(timestamp.getTime()).toDateTime(DateTimeZone.UTC);  

Joda DateTime treats any time in millis like "millis since 1970y in current time zone". So, when you create DateTime instance, it is created with current time zone.

Upvotes: 54

Related Questions