how to parse output of new Date().toString()
Asked Answered
B

4

22

I need a date format (maybe SimpleDateFormat) that parses reliable the output I get when I call toString() on a Date object. Output on my german(!) system is: "Sun Dec 12 13:45:12 CET 2010", so it doesn't seem to honor locales, which seems to make it easy.

Anyone?

Beauvoir answered 17/1, 2011 at 13:45 Comment(0)
T
32

That format is specified in the Date#toString().

Converts this Date object to a String of the form:

dow mon dd hh:mm:ss zzz yyyy

So, in SimpleDateFormat pattern terms:

EEE MMM dd HH:mm:ss zzz yyyy

Unrelated to the problem, I wonder if it wasn't in first place a bad idea to use Date#toString() instead of SimpleDateFormat#format() to output dates. I would consider to fix it straight there.

Thebes answered 17/1, 2011 at 13:47 Comment(2)
The problem is I got data produced through date.toString()... I would have used DateFormat, also.Beauvoir
TO ALL OTHERS: Please note that you have to initialize the DateFormat with Locale.US to make this work in non-US countries.Beauvoir
B
6

BalusC gave you the correct format, you I'd say - don't. The toString() method must not be used for anything other than logging.

You can use SimpleDateFormat for both formatting and parsing.

Barnaba answered 17/1, 2011 at 13:49 Comment(1)
Note that java.sql.Date has a different toString() result.Fransen
H
2

TL;DR

    Instant parsedBack = Instant.parse(Instant.now().toString());
    System.out.println(parsedBack);

2019-05-30T08:36:47.966274Z

Use ISO 8601 and java.time

  1. If your real goal is to serialize and deserialize a date and time (for data transfer or for persistence, for example), serialize to ISO 8601, the standard format for date and time data.
  2. Skip the long outdated Date class. The modern Java date and time API known as java.time is so much nicer to work with. The class you need from it is probably Instant (this depends on your more exact requirements).

The two points go nicely hand in hand:

    Instant i = Instant.now();
    String s = i.toString();
    Instant theSameInstant = Instant.parse(s);

The modern classes’ toString methods produce ISO 8601 format (e.g., 2018-01-11T10:59:45.036Z), and their parse methods read the same format back. So this snippet is all you need, and you get an instant equal to the first, with nanosecond precision.

If you cannot control the string you get, and you get the result from Date.toString(), the format pattern string in BalusC’s answer works with java.time too:

    DateTimeFormatter dtf 
            = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
    Date d = new Date();
    String s = d.toString();
    Instant nearlyTheSameInstant = ZonedDateTime.parse(s, dtf).toInstant();

Some warnings, though:

  1. Milliseconds from the original Date are lost since they are not in the string, leading to an inaccuracy of up to 999 milliseconds (which was why I named the variable nearlyTheSameInstant).
  2. The era from the original Date is not in the string either. So if your original Date was in year 44 BCE, you will get the corresponding date in year 44 CE (AD) (in which case the variable name nearlyTheSameInstant was a lie anyway).
  3. The time zone abbreviation in the string is often (most often?) ambiguous, so there is a great risk of getting the wrong time zone and hence a wrong time. To make matters worse, an ambiguous time zone abbreviation will be interpreted differently on different JVMs
  4. It’s essential to provide a locale. Otherwise the JVM’s default locale will be used, and if it’s not English, parsing will fail. In the worst case you will see your code running fine for many years and suddenly it will break when one day someone runs it on a computer or device with a different locale setting. I use Locale.ROOT for “the locale neutral locale” or “don’t apply any locale specific processing”. It seems to be the correct approach here.

Links

H answered 30/5, 2019 at 8:47 Comment(3)
Good lord, I needed (and got!) the answer 8 years ago! Thanks anyway, if I need this again I will try your way :).Beauvoir
Your question has got some later duplicates. I wrote this answer on the occasion of this duplicate question: How to convert this string “Mon Jan 01 00:00:00 AEDT 1990” into “1990101”? [duplicate] to help the questioner there.H
Great post covering the strength of Instant but also it's shortcomings! However, the fact that Instant's toString is reverse-convertible with Instant.parse is a very good trait that I will really prefer for most of the time.Yahweh
I
0

you can use jdk8's DateTimeFormatter

DateTimeFormatter dtf
            = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
    Date d = new Date();
    String s = d.toString();
    Instant nearlyTheSameInstant = ZonedDateTime.parse(s, dtf).toInstant();
    Date nearlyTheSameInstantDate = Date.from(nearlyTheSameInstant);
    DateTime dateTime = new DateTime(nearlyTheSameInstantDate);
    String str = dateTime.toString("yyyy/MM/dd");
    System.out.println("str = " + str);
Injurious answered 13/8, 2020 at 5:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.