how to parse output of new Date().toString()
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?
That format is specified in the Date#toString()
.
Converts this
Date
object to aString
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.
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.
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
- 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.
- Skip the long outdated
Date
class. The modern Java date and time API known asjava.time
is so much nicer to work with. The class you need from it is probablyInstant
(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:
- 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 variablenearlyTheSameInstant
). - The era from the original
Date
is not in the string either. So if your originalDate
was in year 44 BCE, you will get the corresponding date in year 44 CE (AD) (in which case the variable namenearlyTheSameInstant
was a lie anyway). - 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
- 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
- Oracle tutorial: Date Time explaining how to use java.time.
- Wikipedia article: ISO 8601