JS Intl.DateTimeFormat hours start at 7 - javascript

When I run:
const date = Intl.DateTimeFormat('en-us', {
second: "2-digit",
minute: "2-digit",
hour: "2-digit"
}).formatToParts(0);
console.log(date);
it says that that the hour is 7, but shouldn't it be 0? I was thinking it might be something with PST being offset 7 hours from UTC but I'm not sure how to fix that.

The time value of a Date is based on UTC, but the default stringified values for Date parts are based on local time. So your assumption about PST offset is correct.
You will get the expected result if you set the output timezone to UTC:
const date = Intl.DateTimeFormat('en-us', {
second: "2-digit",
minute: "2-digit",
hour: "2-digit",
hour12: false,
timeZone: 'UTC'
}).formatToParts(0);
console.log(date);
Note that you must set hour12 to false, otherwise it will return 12 am.
If you get hour 24 instead of 0, set hourCycle to "h23". The hour cycle should be set by the language ('en-US'), however it may not. Setting the hourCycle should override the default to ensure you get 0 for midnight not 24.

Related

Get milliseconds for custom date in custom timezone

I have a date server api that works in Europe/Moscow timezone. The selected date must be sent from the client as a timestamp for the Europe/Moscow timezone.
A client from Canada choosing a date in the calendar, say November 8, 2011 has to send the timestamp in the Europe/Moscow timezone.
I can solve this problem through moment.js, but unfortunately, for certain reasons I can't use third-party libraries in the project.
Basically I need a function that does the same thing as the moment.tz method:
moment.tz('2021-11-08T00:00:00', 'Europe/Moscow');
You can use Intl.DateTimeFormat with suitable options to get a timestamp for any IANA location. The formatToParts method gets the required values, then it's just a matter of formatting them. E.g.
function toLocTimestamp(loc, date = new Date()) {
let {year, month, day, hour, minute, second, timeZoneName} = new Intl.DateTimeFormat('en', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: loc,
timeZoneName: 'short'
}).formatToParts().reduce((parts, part) => {
parts[part.type] = part.value;
return parts;
}, Object.create(null));
// Check if timezone not offset and fix
if (!/\d/.test(timeZoneName)) {
timeZoneName = date.toLocaleString('fr',{
hour: 'numeric',
timeZone: loc,
timeZoneName: 'short'
}).match(/\S+$/)[0];
}
// Change timeZoneName to offset
let sign = timeZoneName.substring(3,4);
let offset = timeZoneName.substring(4);
let [offH, offM] = offset.split(':');
// Return timestamp
return `${year}-${month}-${day}T${hour}:${minute}:${second}${sign}${offH.padStart(2,'0')}:${offM || '00'}`;
}
// E.g.
['Europe/Moscow', 'Asia/Kolkata','Australia/Lord_Howe',
'America/St_Johns'].forEach(
loc => console.log(`${loc.padEnd(20,' ')}: ${toLocTimestamp(loc)}`)
);
The timeZoneName fix is required as depending on the language passed to dateTimeFormat and host system language, the offset might be GMT±H[:mm], UTC±H[:mm] or an abbreviation like "ChST" or "CET". If en returns an abbreviation, fr shouldn't.
This will observe DST for various locations. If a fixed offset is required, just adjust the UTC time by the offset, use toISOString to get the timestamp and remove the trailing Z.

How to format the date to (dd/mm/yyyy hh:mm:ss)

How can I convert the date below into this template (dd/mm/yyyy hh:mm:ss) ?
05/04/2021 14:52
I tried to do it that way, but I only get the time and not the date with time.
var data = new Date('05/04/2021 14:52');
var time = data.toLocaleTimeString('pt-PT', {hour12: false});
console.log(time);
You can use below script
var data = new Date('05/04/2021 14:52');
console.log(data.toLocaleString('en-GB',{hour12: false}));
Output : "04/05/2021, 14:52:00"
If you need more date-related staff than simple date formatting, you can use Moment.js.
moment().format('MMMM Do yyyy, h:mm:ss a'); // April 5th 2021, 9:16:13 pm
moment().format('DD/MM/yyyy hh:mm'); // 05/04/2021 21:18
If you need to format your date object, simply use:
moment(date).format('DD/MM/yyyy hh:mm');
Moment.js is also useful for operation on dates like days, week, month adding/subtracting, getting the start of a week, month, quarter, and many other useful operations.
This is my solution. If you want to create a advanced format, you can read more about object Intl
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl
const formatDate = new Intl.DateTimeFormat("en" , {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false
});
console.log(formatDate.format(new Date('05/04/2021 14:52')))

Intl.DateTimeFormat returns an hour over 24

I have the following Unix timestamp: 1611328500000 (Fri Jan 22 2021 10:15:00 GMT-0500 (Eastern Standard Time)).
I need to display it in Korean Standard Time. To do so, I'm using Intl.DateTimeFormat. However, for some reason, the result I'm getting is 24:15 when I attempt to format it. Unless I'm delusional, I'm pretty sure that's higher than a 24-hour clock usually goes (0:00 to 23:59).
Google tells me my result should be 0:15, obviously on the following date (Sat Jan 22).
Here's a minimal working example:
const date = new Date(1611328500000);
const timeOptions = {
hour12: false,
hour: '2-digit',
minute: '2-digit'
};
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'Asia/Seoul', ...timeOptions
});
console.log(formatter.format(date));
Am I crazy? Can times go up to 24:15 in some circumstances? What is happening here?
EDIT: I just found this page which seems to be experiencing a similar problem. The answer provided there points me towards something called hourCycle, with a link to MDN's Intl.DateTimeFormat.
However, hourCycle only appears once on that page, in the browser support section. Adding the suggested hourCycle: h11 to my timeOptions did not work.
Digging further, I found this page, which lists h23 as a valid option. Surely this is what I'm after! But, alas... my result is still 24:15.
Switch from hour12: true to hourCycle: 'h23' to display the hours from 00:00 to 23:59.
const date = new Date(1611328500000);
const timeOptions = {
hourCycle: 'h23',
hour: '2-digit',
minute: '2-digit'
};
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'Asia/Seoul', ...timeOptions
});
console.log(formatter.format(date));
I used the below code and it worked to transform the input 3000000 milliseconds to the output 00:50:00.000Z
const dateInMilliseconds = 3000000
const formatterConfig = {
hour: "numeric",
minute: "numeric",
second: "numeric",
hourCycle: "h23",
timeZone: "UTC",
fractionalSecondDigits: 3
}
const dateInFormat = new Intl.DateTimeFormat([], formatterConfig).format(dateInMilliseconds)+'Z';
// 00:50:00.000Z

React format string date to date format timzone

When I call my function:
formatDate(new Date("2020-06-08T10:37:05.915+0000")
function formatDate(tstamp) {
return new Intl.DateTimeFormat("en-GB", {
year: "numeric",month: "2-digit",day: "2-digit",
hour: "2-digit", minute: "2-digit",second: "2-digit"
}).format(tstamp);
}
My output is: 08/06/2020, 12:37:05
why I got (12:37:05) instead (10:37:05) my timezone is GMT+2.
It is because the input is GMT+0000 and you are GMT+0200 which is 2 hours ahead Greenwich Mean Time. The format method formats a date without changing its time value.

How to get correct output of hour: "2-digit" for toLocaleString("en-US") with AM/PM?

According to the toLocaleString() MDN Documentation the option hour: "2-digit" should return a 2 digit representation of the hour, but it returns only 1 digit if the locale is en-US and the format is AM/PM. (Update: AM/PM mention)
let d = new Date("2019-05-03 15:00:00").toLocaleString("en-US", {hour: "2-digit", minute: "2-digit"});
console.log(d);
Is there a workaround or another easy way to get the 2-digit hour for the US locale, displaying the AM and PM?
You just have to explicitly disable the 12 hour representation in the options :
let d = new Date("2019-05-03 15:00:00").toLocaleString("en-US", {hour: "2-digit", minute: "2-digit", hour12: false});
console.log(d);
The 2 digits parameter might be related to padding, but I don't think it's absolutely necessary. I would consider removing it.
let d = new Date("2019-05-03 15:00:00").toLocaleString("en-US", {hour12: false});
console.log(d);

Categories

Resources