Reputation: 4369
I try to format a time interval using SimpleDateFormat.
import java.text.*;
import java.util.*;
public class DateFormatTest {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
long interval = 1000;
System.out.println("Interval in millis: " + interval);
System.out.println("Expected result: 00:00:01");
System.out.println("Result using Date and SimpleDateFormat: " +
sdf.format(new Date(interval)));
}
}
I get the following result:
Interval in millis: 1000
Expected result: 00:00:01
Result using Date and SimpleDateFormat: 01:00:01
I am in GMT+1 time zone. But it should not be reflected in the result.
Of course it can be solved with System.out.printf, but what I am searching is the reason.
Upvotes: 3
Views: 572
Reputation: 338795
You are using the wrong class. You are trying to represent a duration of milliseconds and a time-of-day. Neither fits the Date
class. That class represents a moment (a date, with time-of-day, in context of UTC).
Also, java.util.Date
is a terrible class, designed by people who did not understand date-time handling. Now obsolete.
The modern solution uses java.time classes.
LocalTime
Specifically, LocalTime
for a time-of-day using a generic 24-hour day, without a date, and without the context of a time zone or offset-from-UTC.
The start of a day for generic days is 00:00:00. We have a constant for that: LocalTime.MIN
. But know that in various time zones, on various dates, the day may start at another time such as 01:00:00.
LocalTime lt = LocalTime.of( 15 , 30 ) ; // 3:30 PM.
Duration
To represent a span-of-time unattached to the timeline, on a scale of hours-minutes-seconds, use Duration
class.
Duration d = Duration.ofMilliseconds( 1_000 ) ;
We can do math with date-time objects.
LocalTime lt = LocalTime.MIN.plus( d ) ;
You should know that java.time classes use a resolution of nanoseconds, much finer than the milliseconds used by the legacy date-time classes.
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?
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: 1
Reputation: 1500903
I am in GMT+1 time zone. But it should not be reflected in the result.
Then you should set the time zone in the SimpleDateFormat
. SimpleDateFormat
is doing exactly the right thing - it's formatting the instant in time (just after midnight UTC 1970) in the time zone it's working in.
To change the time zone, just use:
sdf.setTimeZone(TimeZone.getTimeZone("etc/UTC"));
It's not clear whether you should really be using SimpleDateFormat
at all, though. You're not trying to format a date/time - you're trying to format an interval, given your variable name.
I suggest you use Joda Time which has a much richer type system, and will allow you to express what you really want.
Also, if you really want to use SimpleDateFormat
, you probably want to use HH
instead of hh
in your format string. (hh
is a 12-hour value, 1-12. You want 00:00:01, not 12:00:01.) hh
is rarely appropriate when you don't also have an am/pm designator in your pattern.
Upvotes: 3
Reputation: 328649
I am in GMT+1 time zone. But should not be reflected in the result.
What makes you think so? new Date(0)
is at 00:00AM GMT on Jan 1st 1970. So it is at 01:00AM if your default timezone is GMT + 1.
Upvotes: 4