How to Parse Output of New Date().Tostring()

how to parse output of new Date().toString()

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.

Parsing a java Date back from toString()

If you don't have control over the code that's generating the String:

To parse the toString() format you need to set the SimpleDateFormat locale to english and use the format: "EEE MMM dd HH:mm:ss Z yyyy".

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", new Locale("us"));`

Parse Javascript new Date().toString() in Swift

As mentioned in the comments by @Sweeper - The timezone name part is implementation dependent - which can be confirmed from the docs

Optionally, a timezone name consisting of:
space
Left bracket, i.e. "("
An implementation dependent string representation of the timezone, which might be an abbreviation or full name (there is no standard for names or abbreviations of timezones), e.g. "Line Islands Time" or "LINT"
Right bracket, i.e. ")"

So we need to - remove the part within parentheses at the end and parse the rest - as mentioned by @Joakim Danielson

Taking this into account, we can do it like this -

extension String {

static private var jsDateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z"
return formatter
}()

func parsedDate() -> Date? {
let input = self.replacingOccurrences(of: #"\(.*\)$"#, with: "", options: .regularExpression)
return String.jsDateFormatter.date(from: input)
}

}

Tests

func testJSDateParsing() {
[
"Tue Jun 01 2021 14:11:27 GMT+0900 (JST)",
"Tue Jun 01 2021 14:03:45 GMT+0900 (Japan Standard Time)",
"Mon May 31 2021 17:38:31 GMT+0800 (中国標準時)",
"Mon May 31 2021 19:25:37 GMT+0930 (オーストラリア中部標準時)",
].forEach({
if let date = $0.parsedDate() {
print("Parsed Date : \(date) for input : \($0)")
}
else {
print("Failed to parse date for : \($0)")
}
})
}

Output

Parsed Date : 2021-06-01 05:11:27 +0000 for input : Tue Jun 01 2021 14:11:27 GMT+0900 (JST)
Parsed Date : 2021-06-01 05:03:45 +0000 for input : Tue Jun 01 2021 14:03:45 GMT+0900 (Japan Standard Time)
Parsed Date : 2021-05-31 09:38:31 +0000 for input : Mon May 31 2021 17:38:31 GMT+0800 (中国標準時)
Parsed Date : 2021-05-31 09:55:37 +0000 for input : Mon May 31 2021 19:25:37 GMT+0930 (オーストラリア中部標準時)

toString() returns unexpected things on a Date object

According to your need, you can just use json.getString("date_1").

You don't need to set extra logics. Parsing is needed when you want to convert String date to Date object for some calculation.

If you want to change format of received date then use this method.

changeStringDateFormat(json.getString("date_1"), "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd");

Just put this method inside your Util.

public String changeStringDateFormat(String date, String inputDateFormat, String outPutDateFormat) {
Date initDate = null;
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(inputDateFormat);
initDate = simpleDateFormat.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
SimpleDateFormat outputFormatter = new SimpleDateFormat(outPutDateFormat);
String parsedDate = outputFormatter.format(initDate);
return parsedDate;
}

See Java Date Doc, It returns string from default format.

public String toString()

Converts this Date object to a String of the form:

dow mon dd hh:mm:ss zzz yyyy

How to parse a string into a Java Date?

Your pattern is not correct, it contain many problems :

  • EEEE replace with EEE
  • , remove this because your string not have comma
  • , same thing for the second comma
  • replace the position of yyyy and put in the end
  • a remove as it is not used at all, and instead use z to match ETC

If you are using java-time you can parse your date using this pattern EEE MMM dd HH:mm:ss z yyyy :

DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"EEE MMM dd HH:mm:ss z yyyy",
Locale.US);
ZonedDateTime zdt = ZonedDateTime.parse(str, formatter);

Parsing a string to a date in JavaScript

The best string format for string parsing is the date ISO format together with the JavaScript Date object constructor.

Examples of ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS.

But wait! Just using the "ISO format" doesn't work reliably by itself. String are sometimes parsed as UTC and sometimes as localtime (based on browser vendor and version). The best practice should always be to store dates as UTC and make computations as UTC.

To parse a date as UTC, append a Z - e.g.: new Date('2011-04-11T10:20:30Z').

To display a date in UTC, use .toUTCString(),

to display a date in user's local time, use .toString().

More info on MDN | Date and this answer.

For old Internet Explorer compatibility (IE versions less than 9 do not support ISO format in Date constructor), you should split datetime string representation to it's parts and then you can use constructor using datetime parts, e.g.: new Date('2011', '04' - 1, '11', '11', '51', '00'). Note that the number of the month must be 1 less.


Alternate method - use an appropriate library:

You can also take advantage of the library Moment.js that allows parsing date with the specified time zone.

DateTimeFormatter for Javascript Date.toString output

Dates in JavaScript is a big mess. toString() is not only browser/implementation dependent, but also locale sensitive. I'm in Brazil, so my browser is set to Portuguese, and new Date().toString() gives this result:

Wed Apr 04 2018 14:14:04 GMT-0300 (Hora oficial do Brasil)

Month and day-of-week names are in English, but the timezone name is in Portuguese. What a mess!

Anyway, to parse those strings, you have to make some decisions.

Do you need to get the timezone or just the offset?

The offset GMT+0200 is used by more than one country (hence, more than one timezone uses it). Although the offset is enough to have a non-ambiguous point in time, it's not enough to know the timezone.

Even short names such as CEST are not enough, because this is also used by more than 1 country.

If you want to parse just the offset, the best way is to simply remove everything after the ( and parse it to an OffsetDateTime:

DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.US);

// 2018-04-04T16:12:41+02:00
OffsetDateTime.parse("Wed Apr 04 2018 16:12:41 GMT+0200", parser);

Also note that I used a java.util.Locale. That's because the month and day of week are in English, and if you don't set a locale, it'll use the JVM default - and you can't guarantee that it'll always be English. It's better to set a locale if you know in what language the inputs are.

If you need to get the timezones, though, it's more complicated.

Names like "CEST" are ambiguous, and you need to make arbitrary choices for them. With java.time is possible to build a set of preferred timezones to be used in case of ambiguities:

Set<ZoneId> zones = new HashSet<>();
zones.add(ZoneId.of("Europe/Berlin"));
zones.add(ZoneId.of("America/Bogota"));
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z (")
// optional long timezone name (such as "Colombia Time" or "Pacific Standard Time")
.optionalStart().appendZoneText(TextStyle.FULL, zones).optionalEnd()
// optional short timezone name (such as CET or CEST)
.optionalStart().appendZoneText(TextStyle.SHORT, zones).optionalEnd()
// close parenthesis
.appendLiteral(')')
// use English locale, for month, timezones and day-of-week names
.toFormatter(Locale.US);

With this, you can parse your inputs to a ZonedDateTime:

// 2018-04-04T16:12:41+02:00[Europe/Berlin]
ZonedDateTime.parse("Wed Apr 04 2018 16:12:41 GMT+0200 (CEST)", fmt);

// 2018-04-04T10:25:10-05:00[America/Bogota]
ZonedDateTime.parse("Wed Apr 04 2018 10:25:10 GMT-0500 (Colombia Time)", fmt);

But unfortunately, this doesn't parse the "SA Pacific Standard Time" case. That's because the timezones names are built-in in the JVM and "SA Pacific Standard Time" is not one of the predefined strings.

A good alternative is to use the mapping suggested by M.Prokhorov in the comments: https://github.com/nfergu/Java-Time-Zone-List/blob/master/TimeZones/src/TimeZoneList.java

Then you manually replace the name in the string and parse it with VV pattern (instead of z), because the mapping uses IANA's names (such as Europe/Berlin, which are parsed by VV).


But the best alternative is to use toISOString(), which produces strings in ISO8601 format, such as 2018-04-04T17:39:17.623Z. The big advantage is that java.time classes can parse it directly (you don't need to create a custom formatter):

OffsetDateTime.parse("2018-04-04T17:39:17.623Z");


Related Topics



Leave a reply



Submit