Scott M
Scott M

Reputation: 41

Joda DateTime getMillis() for UTC is incorrect, returning local milliseconds instead

I am trying to get the UTC milliseconds to convert a Joda DateTime instance to a SQL Timestamp, however it is converting it to my local time instead.

This is an example:

DateTime d = DateTime.now().withZone(DateTimeZone.UTC);
Timestamp t = new Timestamp(d.getMillis());
System.out.println(t);
t.setHours(d.getHourOfDay());
System.out.println(t);

And the output:

2015-04-17 18:11:27.277
2015-04-17 22:11:27.277

Why is it converted to my local timezone? I thought the DateTime.getMillis() method always returned the milliseconds for UTC?

Upvotes: 4

Views: 5256

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338516

tl;dr

ZonedDateTime.now()

Instant

The Joda-Time library was replaced by the java.time classes built into Java 8 and later.

Instead of DateTime class, use java.time.Instant to represent a moment as seen in UTC (an offset of zero hours-minutes-seconds).

Instant now = Instant.now() ;

ZonedDateTime

You can adjust to see that moment through the wall-clock/calendar of a particular time zone. Use ZonedDateTime class.

ZoneId z = ZoneId.of( "America/Edmonton" ) ;  // Or ZoneId.systemDefault()
ZonedDateTime zdt = now.atZone( z ) ;

Or skip the Instant and go directly to capturing the current moment as a ZonedDateTime object.

ZonedDateTime zdt = ZonedDateTime.now( z ) ;

Avoid legacy date-time classes

You said:

new Timestamp

Never use java.sql.Timestamp. This class is a disaster of poor design and confusing documentation. Entirely replaced with java.time classes.

Upvotes: 1

durron597
durron597

Reputation: 32323

When you change the time, you don't change the number of milliseconds since the epoch. In other words, calling withZone doesn't actually change the underlying long millis.

The real problem is the Timestamp.setHours method, which has been deprecated since Java 1.1. See the documentation:

@Deprecated

public void setHours(int hours)

Deprecated. As of JDK version 1.1, replaced by Calendar.set(Calendar.HOUR_OF_DAY, int hours). Sets the hour of this Date object to the specified value. This Date object is modified so that it represents a point in time within the specified hour of the day, with the year, month, date, minute, and second the same as before, as interpreted in the local time zone.

Upvotes: 4

IndieTech Solutions
IndieTech Solutions

Reputation: 2541

try this:

DateTimeZone.setDefault(DateTimeZone.UTC);
DateTime d = DateTime.now();
Timestamp t = new Timestamp(d.getMillis());
System.out.println(t);
t.setHours(d.getHourOfDay());
System.out.println(t);

Upvotes: 1

Related Questions