13

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
Menno
  • 12,175
  • 14
  • 56
  • 88

3 Answers3

41

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
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Oh my... so, is it possible for me to convert a long without any timezones interfering? – Menno Jan 02 '13 at 15:42
  • 2
    The stuff I know is so random, it's not even useful for Trivial Pursuit ;) – Peter Lawrey Jan 02 '13 at 15:43
  • Ah great, thanks for your help Peter. I will accept your answer as soon as Stackoverflow allows me to do so. – Menno Jan 02 '13 at 15:47
  • 1
    If someone want to know why, he can read about, BST (British Summer Time). That period was a failed experiment to bring it back to life. – Damian Leszczyński - Vash Jan 02 '13 at 15:47
  • 6
    Apparently it was an experiment called British Standard Time. Wikipedia: Analysis of accident data for the first two years of the experiment indicated that while there had been an increase in casualties in the morning, there had been a substantially greater decrease in casualties in the evening, with a total of around 2,700 fewer people killed and seriously injured during the first two winters of the experiment, at a time when about 1,000 people a day were killed or seriously injured on the roads. – ARC Jan 02 '13 at 15:48
  • 1
    @ARC Sounds like they should have kept it. For me it's dark on the way to work and dark on the way home in winter so `GMT+0` or `GMT+1` makes no difference to me. – Peter Lawrey Jan 02 '13 at 15:50
  • Well, I just love how results for experiments can be skewed if you conveniently forget to mention other aspects of the time period. For example, the fact that drunk driving laws were implemented around that time and people (hopefully) only drink in the evenings. – ARC Jan 02 '13 at 17:27
  • 1
    @ARC In Australia there is law which determines how close the front windows of houses facing each other can be. It was based on how far someone in England determined you would be able to see someone undressing if there houses were closer (under lighting conditions in England) ;) – Peter Lawrey Jan 02 '13 at 17:30
  • @Peter Lawrey Further evidence of the absolutely random facts you know. – ARC Jan 02 '13 at 18:38
  • @ARC The earth weighs about the same as 1.4*10^27 sugar cubes. (had to check as it's been a while since I used that info ;) – Peter Lawrey Jan 02 '13 at 18:42
  • @PeterLawrey You did **use** that info ? – Denys Séguret Jan 03 '13 at 13:32
  • @dystroy The last time I claimed to know some useless facts. ;) I read it in a book once. – Peter Lawrey Jan 03 '13 at 13:35
2

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.

richardtz
  • 4,993
  • 2
  • 27
  • 38
  • Yes, I noticed the difference. Hence the question as to what causes it. But Peter already covered it perfectly. – Menno Jan 02 '13 at 15:44
  • I don't think it's due to London/Paris time zone in 1970-01-01. AFAIK the Date(0) is built like that (with getHours()==1) anywhere in the world, i.e. regardless of the default system timezone. Check http://stackoverflow.com/a/41615128/1141215. – PJ_Finnegan Jan 12 '17 at 14:26
  • 1
    It *is* because of time zone, @PJ_Finnegan. However I recommend we don’t use `Date`. That class is poorly designed and long outdated. Instead use `Instant` and other classes from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jun 04 '19 at 13:13
  • @Ole V.V. I'm not in the London/Paris timezone but I used to get a +1 offset as well on the hours when I created a Date(0) – PJ_Finnegan Jun 05 '19 at 14:23
  • @PJ_Finnegan Which time zone are you in and what do you get from `new Date(0)`? When I set my JVM’s default time zone to Asia/Tokyo and try `new Date(0)`, I get `Thu Jan 01 09:00:00 JST 1970`. With Asia/Kolkata I get `Thu Jan 01 05:30:00 IST 1970`. – Ole V.V. Jun 05 '19 at 14:29
  • @OleV.V. Europe/Rome, and you can see my results in the link I posted in the original comment. – PJ_Finnegan Jun 06 '19 at 15:41
  • Thanks, @PJ_Finnegan. Rome too was at GMT offset +01:00 on 1 January 1970, which explains why you get 01:00:00 (if in doubt: on https://www.timeanddate.com/time/zone/italy/rome, in the dropdown select 1960 — 1969 and see that the last change in 1969 was when summer time ended on 28 September and offset UTC+1h began). – Ole V.V. Jun 06 '19 at 15:46
1

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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161