I have a function in Java to convert an Epoch date to ISO 8601, but I've come across the need to do it in Javascript. I have it somewhat working in JS but it needs to be localized to the timezone.
Java version:
public static String epochToIso8601(long time, String Zone) {
String format = "yyyy-MM-dd'T'HH:mm:ssX";
TimeZone timeZone = TimeZone.getTimeZone(Zone);
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
sdf.setTimeZone(timeZone);
return sdf.format(new Date(time));
}
Param1: -157737600000
Param2: PST
Output: 1965-01-01T00:00:00-08
My attempt in Javascript:
function epcov(epoch, timezone)
{
var someValueNum = Number(epoch);
var s = new Date(someValueNum);
return s.toISOString();
}
Essentially I want the same thing that's coming out of Java, but it's outputting: 1965-01-01T08:00:00.000Z
By the way, I'm already splitting the date and time up from something that looks like this, so if there is a better to just pass in the following as one string and let Javascript parse it, that would be amazing:
/Date(-157737600000-0800)/
CodePudding user response:
We can convert the string /Date(-157737600000-0800)/
to a unix time (in ms), and a UTC offset in HHMM using String.match()
.
The HHMM UTC offset can then be converted to a UTC offset in milliseconds by multiplying the HH value by 3600000 and the MM value by 60000.
We then create a new Date object using the unix time and offset values, since we know the exact offset at that point in time.
We then format using Date.toISOString()
and replace the 'Z' UTC offset timezone value with the actual UTC offset string (e.g. '-08:00').
function parseAndFormatDate(date) {
const [,millis, offset] = date.match(/([ \-] \d )([ \-] \d )/);
const offsetMillis = (offset.slice(0, 1) '1') * (offset.slice(1, 3) * 3600000 offset.slice(-2) * 60000);
const formattedOffset = offset.slice(0, 3) ':' offset.slice(-2);
return new Date( millis offsetMillis).toISOString().replace('Z', formattedOffset);
}
console.log(parseAndFormatDate('/Date(-157737600000-0800)/'));
console.log(parseAndFormatDate('/Date( 1664271413000 0100)/'));
.as-console-wrapper { max-height: 100% !important; }
CodePudding user response:
I hope this helps you in some way.
JS doesn't have good (any?!) support for exporting an ISO 8601 string in a specified time zone. So you have to construct the string yourself, manually.
The use of the Swedish locale is to get an ISO 8601-like basis from which to pull the elements of the date time. Unfortunately there is no ISO 8601 "formatting locale".
// Get wall clock date at the specified tz in IS0 8601
const getISO8601Date = (d, timeZone) =>
d.toLocaleString('sv-SE', { timeZone, dateStyle: 'short'})
// Get wall clock time at the specified tz in IS0 8601
const getISO8601Time = (d, timeZone) =>
d.toLocaleString('sv-SE', { timeZone, timeStyle: 'medium'})
// Get time zone offset in specified tz in IS0 8601
const getISO8601TimeZoneOffset = (d, timeZone) => {
const s = d.toLocaleString('sv-SE', { timeZone, timeZoneName: 'longOffset' })
const result = /GMT(?<offset>[ −]\d\d:\d\d)/.exec(s) // Use regexp to pull out offset
return result ? result.groups.offset : 'Z'
}
// Put together an ISO 8601 string representing the wall clock at the specified date, in the specified timezone
const getISO8601Dtg = (d, timeZone) =>
`${getISO8601Date(d, timeZone)}T${getISO8601Time(d, timeZone)}${getISO8601TimeZoneOffset(d, timeZone)}`
const d = new Date(-157737600000)
console.log(getISO8601Dtg(d, 'PST')) // 1965-01-01T00:00:00−08:00