Recently I came across an interesting problem when dealing with date. When using javascript date object, chrome and safari render different result with the same date string. If I run new Date('2017-09-04T09:52:15')
in browser deveopler console, chrome will output Mon Sep 04 2017 09:52:15 GMT+0800 (CST)
and safari will output Mon Sep 04 2017 17:52:15 GMT+0800 (CST)
.
The reason is obvious if you compare the result carefully. Since I lose my timezone information in the date string, the two browsers react differently to this situation. Chrome will take your computer's timezone as default timezone when parsing the date string. Meanwhile safari will take the string as UTC time.
If we could add timezone information to the date string, there won't be such problem. The question is how we add timezone to the date string. Fortunately there is something called ISO date format. The format is as follows:
YYYY-MM-DDTHH:mm:ss.sssZ
Specific descriptions of each symbol can be found on Microsoft Docs. If you append Z
to the end of the above string and run new Date('2017-09-04T09:52:15Z')
, chrome and safari will output the same result. Bingo! We got it.
Make ISO Date Format Localized
ISO date format is simple but it's not intuitive because we are used to our own timezone which means it needs to be formatted to local date time. Let's see how we can realize that.
JavaScript
const isoDateString = "2017-09-04T09:52:15.000Z";
const localizedDateString = new Date(isoDateString).toLocaleString();
console.log(localizedDateString); // "9/4/2017, 5:52:15 PM"
Java
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.temporal.TemporalAccessor;
public class ISODateStringToLocalizedDateString {
public static void main(String[] args) {
String isoDateString = "2017-09-29T15:47:36.504Z";
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
TemporalAccessor accessor = formatter.parse(isoDateString);
Date date = Date.from(Instant.from(accessor));
SimpleDateFormat dateFormatter = new SimpleDateFormat();
String localizedDateString = dateFormatter.format(date);
System.out.println(localizedDateString); // "9/29/17 11:47 PM"
}
}
Swift
import UIKit
var dateString = "2017-09-04T09:52:15.000Z"
dateString = "\(dateString.components(separatedBy: ".")[0])Z"
let date = ISO8601DateFormatter().date(from: dateString)!
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .short
dateFormatter.string(from: date) // "9/4/17, 5:52 PM"
Convert Local Date to ISO Date Format
I got the date string without timezone information from server. So it's reasonable to blame the back-end developer. But when client submit date to server timezone information should also be included.
JavaScript
new Date(2017, 09, 04, 17, 30, 30).toISOString(); // "2017-09-29T15:46:22.164Z"
Java
import java.util.Date;
import java.text.SimpleDateFormat;
public class LocalDateStringToISODateFormat {
public static void main(String[] args) {
try {
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss.SSS");
Date date = df.parse("16/10/2015 15:25:07.861");
String ISODateString = date.toInstant().toString();
System.out.println(ISODateString);
} catch (Exception e) {
System.out.println(e);
}
}
}
new Date().toInstant().toString() // "2017-09-29T15:47:36.504Z"
Swift
import UIKit
let localDateString = "2017-09-04 17:30:30"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = dateFormatter.date(from: localDateString)!
var str = ISO8601DateFormatter().string(from: date)
str.insert(contentsOf: ".000", at: str.index(str.endIndex, offsetBy: -1))
print(str)
Only when both client and server pass date as ISO format it could be displayed correctly!