简体   繁体   中英

Java SimpleDateFormat: an hour wrong

I don't need a whole story to clarify my question, so I'll just show the code (which is a mere example). How come there is a difference in my result?

Code

long millis = 2305293L;
System.out.println(
    millis + "ms = " + 
    (millis / 1000) + "s = " + 
    (millis / 1000 / 60) + "m");
System.out.println(
    new SimpleDateFormat("HH:mm:ss").
    format(
        new Date(millis)
        )
    );

Output

2305293ms = 2305s = 38m
01:38:25

If you are in London, or Paris, the timezone was GMT+1 on 1 Jan 1970.

For reasons @ARC explains in the comments, the UK used GMT+1 or UTC+1 from 18 Feb 1968 to 31 Oct 1971

is it possible for me to convert a long without any timezones interfering?

Set the TimeZone to be GMT.

long millis = 2305293L;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(new Date(millis)));

prints

00:38:25.293

Try this :

System.out.println(new java.util.Date (0));

you will see it begins at 01:00:00, hence the difference of one hour.

The other answers are correct and were good answers when the question was asked in 2013. Today we should no longer use Date nor SimpleDateFormat , so I would like to show you a couple of modern code snippets instead. The correct way to format your (in this case) 2 305 293 milliseconds depends on what they represent. I am presenting three options for three different situations.

Formatting a number of milliseconds since the epoch

You need to decide in which time zone you want to interpret your point in time. For example:

    long millis = 2_305_293L;
    DateTimeFormatter formatter = DateTimeFormatter
            .ofLocalizedDateTime(FormatStyle.LONG)
            .withLocale(Locale.ENGLISH);
    ZonedDateTime dateTime = Instant.ofEpochMilli(millis)
            .atZone(ZoneId.of("America/Coral_Harbour"));
    String formattedTime = dateTime.format(formatter);
    System.out.println(formattedTime);

December 31, 1969 at 7:38:25 PM EST

Since at the epoch Coral Harbor was at UTC offset -05:00, we get a time near the end of 1969. If you want the time in UTC (since the epoch is defined in UTC; in other words, if you want 00:38:25 ), it's a bit different:

    DateTimeFormatter formatter = DateTimeFormatter
            .ofLocalizedDateTime(FormatStyle.MEDIUM)
            .withLocale(Locale.ENGLISH);
    OffsetDateTime dateTime = Instant.ofEpochMilli(millis)
            .atOffset(ZoneOffset.UTC);

Jan 1, 1970, 12:38:25 AM

In addition to time zone you may vary the language through the locale and the length of the format through the format style (full, long, medium, short). If you want the time of day without the date, use ofLocalizedTime instead of ofLocalizedDateTime .

Formatting a millisecond of day

Assuming your milliseconds are since 0:00 (“midnight”) in whatever time zone:

    LocalTime time = LocalTime.MIN.with(ChronoField.MILLI_OF_DAY, millis);
    System.out.println(time);

00:38:25.293

If this format is satisfactory, you don't need any explicit formatter. If not, you may use a DateTimeFormatter .

Formatting a duration, an amount of time

An amount of time is a completely different thing from a time and is handled as a Duration object. There is no direct support for formatting it, but since Java 9 it's not so hard (when you know how):

    Duration amountOfTime = Duration.ofMillis(millis);
    String formattedTime = String.format("%02d:%02d:%02d",amountOfTime.toHours(),
            amountOfTime.toMinutesPart(), amountOfTime.toSecondsPart());
    System.out.println(formattedTime);

00:38:25

Link

Oracle tutorial: Date Time explaining how to use java.time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM