Is there a way to get a time that is local to a specified timezone in JavaScript? Basically, I'm looking for a way to say, what is the ISO time string of 2pm in New York?
I have a hack to do so, where the date
is a parse-able date string, and tz
is a timezone identifier, such as America/New_York
.
function getDateInTZ(date, tz) {
const formatter = new Intl.DateTimeFormat([], {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3,
timeZone: tz,
});
const localDate = new Date(date);
const localDateAtTZ = new Date(formatter.format(localDate));
const tzOffset = localDate.getTime() - localDateAtTZ.getTime();
return new Date(localDate.getTime() + tzOffset);
}
and it has the following behavior
getDateInTz("2021-07-01 20:05", "America/Chicago").toISOString(); // 2021-07-02T01:05:00.000Z
getDateInTz(new Date("2021-12-05 20:05"), "America/Chicago").toISOString(); // 2021-12-06T02:05:00.000Z
getDateInTz("2021-12-06T02:05:00.000Z", "America/New_York").toISOString(); // 2021-12-06T02:05:00.000Z if local time is NY
getDateInTz("2021-12-06T02:05:00.000Z", "America/New_York").toISOString(); // 2021-12-06T07:05:00.000Z if local time is UTC
While the above solution works in Chrome, it doesn't work on Firefox because FF is unable to do Date.parse
on the output of formatter.format()
. Which leads me to think that it's not a correct solution.
Has anyone run into this requirement before, and have a good solution for it?
Is there a way to get a time that is local to a specified timezone in JavaScript? Basically, I'm looking for a way to say, what is the ISO time string of 2pm in New York?
I have a hack to do so, where the date
is a parse-able date string, and tz
is a timezone identifier, such as America/New_York
.
function getDateInTZ(date, tz) {
const formatter = new Intl.DateTimeFormat([], {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
fractionalSecondDigits: 3,
timeZone: tz,
});
const localDate = new Date(date);
const localDateAtTZ = new Date(formatter.format(localDate));
const tzOffset = localDate.getTime() - localDateAtTZ.getTime();
return new Date(localDate.getTime() + tzOffset);
}
and it has the following behavior
getDateInTz("2021-07-01 20:05", "America/Chicago").toISOString(); // 2021-07-02T01:05:00.000Z
getDateInTz(new Date("2021-12-05 20:05"), "America/Chicago").toISOString(); // 2021-12-06T02:05:00.000Z
getDateInTz("2021-12-06T02:05:00.000Z", "America/New_York").toISOString(); // 2021-12-06T02:05:00.000Z if local time is NY
getDateInTz("2021-12-06T02:05:00.000Z", "America/New_York").toISOString(); // 2021-12-06T07:05:00.000Z if local time is UTC
While the above solution works in Chrome, it doesn't work on Firefox because FF is unable to do Date.parse
on the output of formatter.format()
. Which leads me to think that it's not a correct solution.
Has anyone run into this requirement before, and have a good solution for it?
Share Improve this question asked Oct 20, 2021 at 5:24 Tri NguyenTri Nguyen 11.2k9 gold badges48 silver badges78 bronze badges 3- Perhaps you really want a vanilla JS solution? Though, I'd highly remend npmjs./package/moment-timezone – FishSaidNo Commented Oct 26, 2021 at 1:28
- @FishSaidNo do you have the code that uses moment-timezone that does what I am mentioning? – Tri Nguyen Commented Oct 27, 2021 at 13:46
- Have a look at this stackoverflow./questions/66630818/… – Corrl Commented Nov 1, 2021 at 15:54
5 Answers
Reset to default 2As far as I know this is not possible without the help of a library like luxon or day.js
In luxon this would be the way to go
let local = luxon.DateTime.local(); // 2021-10-31T20:26:15.093+01:00
let localInCT = local.setZone("America/Chicago"); //2021-10-31T14:26:15.093-05:00
Have a look at this project using these methods
We're limited by the JavaScript native Date object here.
The internal state of a Date object is the number of milliseconds that have elapsed since 1970-01-01 00:00 UTC, and no timezone is stored in the Date object.
So, we can create Dates somewhat equivalent to ones created in another timezone, but they won't behave exactly the same:
The timezone offset for Date.toString() will show the local client timezone (e.g. GMT+0000) rather than the offset in the desired timezone.
DST rules may not work as expected. We can get the equivalent date for say America/New_York, but DST transitions will obey the local timezone rules and not the New York rules.
Having said that, a variant of the approach you're using will give what I would call equivalent dates in the desired timezone.
How we do this:
First use Date.toLocaleString() to format an ISO timestamp in the desired timezone. We use a hack to do this, passing the 'sv' locale to the function. This will create an ISO timestamp, e.g. yyyy-MM-dd HH:mm:ss.
Pass this timestamp to the Date() constructor.
TLDR: This can't really be done. But for some contexts and use cases we can approximate the desired behaviour. I would remend using a library like luxon for this purpose.
Example below:
function getDateInTimezone(date, timeZone) {
// Using a locale of 'sv' formats as an ISO date, e.g. yyyy-MM-dd HH:mm.
const timeInTimeZone = date.toLocaleString('sv', { timeZone } );
// Pass this to the Date constructor
return new Date(timeInTimeZone);
}
const localTime = new Date();
const timeZoneList = ['Asia/Tokyo', 'Europe/Berlin','America/Los_Angeles'];
console.log(`Local Time: ${localTime.toLocaleTimeString()}`);
for(let timeZone of timeZoneList) {
const dt = getDateInTimezone(localTime, timeZone);
console.log(`Time (${timeZone}): ${dt.toLocaleTimeString()}`);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Timezones in luxon are a lot easier to handle, also when we call .toString() on a Luxon DateTime, we get the correct UTC offset.
const { DateTime } = luxon;
const localTime = DateTime.now();
const timeZoneList = ['Asia/Tokyo', 'Europe/Berlin','America/Los_Angeles'];
console.log(`Local Time: ${localTime.toFormat('HH:mm:ssZZ')}`);
for(let zone of timeZoneList) {
const dt = DateTime.fromMillis(Date.now(), { zone });
console.log(`Time (${zone}): ${dt.toFormat(' HH:mm:ssZZ')}`);
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare./ajax/libs/luxon/2.0.2/luxon.min.js" integrity="sha512-frUCURIeB0OKMPgmDEwT3rC4NH2a4gn06N3Iw6T1z0WfrQZd7gNfJFbHrNsZP38PVXOp6nUiFtBqVvmCj+ARhw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
You can use something like this:
const actualDate = new Date()
actualDate.toLocaleString('en-US', { timeZone: 'America/New_York' })
Does this solve your question?
function getDateInTZ(date, tz) {
return new Date(date).toLocaleString('en-US', { timeZone: tz })
}
console.log(getDateInTZ("2021-07-01 20:05", "Asia/Kolkata"))
console.log(getDateInTZ("2021-07-01 20:05", "America/Chicago"))
console.log(getDateInTZ("2021-12-06T02:05:00.000Z", "America/New_York"))
let date = new Date();
let time = date.toLocaleTimeString([], { hour12: true })
if we are using hour12 true it will return the time in 12h format else it will return the time in 24h format make sure we are using TZ on .env file it always been a good practice and helps to erase all the extra code.
you can simply use
TZ=America/New_York
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745256747a4619004.html
评论列表(0条)