Timezone offset by timezone name for a specific date in Javascript - javascript

How can I find timezone offset in hours or minutes using timezone name for a specific date.
Example use would be :
var offset = findOffset("America/New_York", new Date(2019,08,07))
// offset is -4
I am hoping to find a solution using native JS, but if it does not exist I am also ok with using some libraries.

I will recommend Moment Timezone which is a JS library and it is quite popular (3,660,521 weeks NPM downloads). Moment and Moment Timezone are sibling libraries (Same developer).
The moment timezone library gives you offset in the output like shown below:
moment.tz("2013-12-01", "America/Los_Angeles").format(); // 2013-12-01T00:00:00-08:00
moment.tz("2013-06-01", "America/Los_Angeles").format(); // 2013-06-01T00:00:00-07:00

So here is the answer I found
const findTimeZoneOffset = (tz,date) => {
let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(date.toLocaleString('en-US', { timeZone: tz }));
let diff = ( tzDate.getTime() - utcDate.getTime() ) / 1000 / 60 / 60;
return diff;
};
and as expected
findTimeZoneOffset("America/New_York", new Date(2019,08,07))
// returns -4

Related

Converting date formats without timezone conversion?

I'm trying to do this without adding moment js to my project but it seems more difficult than I'd like.
if I get a date that's formatted as : "2021-07-19T12:15:00-07:00"
Is there an efficient way to have it formatted as:
"12:15 pm"
regardless of where me and my browser are located?
I've gotten as far as some other answers with no luck, for example:
var date = new Date('2021-07-19T12:15:00-07:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);
Thanks!
You could use Date.toLocaleTimeString() to format the time, this will give you the time in the local timezone, if we remove the UTC offset.
There are other options available here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
let timestampWithUTCOffset = "2021-07-19T12:15:00-07:00";
let timestampWithoutUTCOffset = timestampWithUTCOffset.substr(0,19);
console.log( { timestampWithUTCOffset , timestampWithoutUTCOffset });
let dt = new Date(timestampWithoutUTCOffset);
console.log('Time of day:', dt.toLocaleTimeString('en-US', { timeStyle: 'short' }))

How can I substract hours from my date using data from a string?

I have a date in UTC in javascript, and I would like to substract some hours.
I searched online and apparently I should concat the substraction to the date like the following:
const diff = "-5"
const utcDate = "2017-02-22 17:28:13"
const date = new Date(utcDate + diff[0] + ' ' + diff[1])
//desired output: 2017-02-22 12:28:13
But I can't seem to make it work.
I do all my Date calculations with .getTime().
So an hour is 3600000 milliseconds.
const MILLISECONDS_HOUR = 3600000;
const diff = -5;
const utcDate_str = "2017-02-22 17:28:13";
const utcDate = new Date( utcDate_str );
const minus_5_hours = new Date( utcDate.getTime() + ( MILLISECONDS_HOUR * diff ));
console.log( utcDate.toJSON());
console.log( minus_5_hours.toJSON());
The big advantage is that javascript will take care of leap years, month boundaries and such.
But since you are calling your variable diff, are you trying to calculate lcoal time vs UTC time?
In that case, reread the javascript Date methods. There's a bunch of methods to handle both UTC and local time, for example: date.getUTCDate() and date.getDate().
So you might not have to calculate all of this yourself.
Also, if you format your dates according to the ISO, "2017-02-22T17:28:13.000Z", this will automatically get parsed as UTC.
someDate.setHours(someDate.getHours()+1);
From https://stackoverflow.com/a/1050782/537998

Changing time on hosted site

I'm trying to convert date/time into local time, instead of UTC.
I'm getting the date and time from an API and this is giving it on UTC. So I need to convert it from UTC to local time, because after 6:00 pm it displays the date for the next day.
I've tried moment and 'toString', and it works on localhost but if I host it it still gives me UTC
let dateTesting = subscription.current_period_started_at._
let dateTesting2 = moment.utc(dateTesting).local().format('MM-DD- YYYY HH:mm:ss')
let dateTesting3 = dateTesting.toString("MM/dd/yyyy HH:mm")
console.log('- now in UTC', dateTesting)
console.log('dateTesting2 -------', dateTesting2)
console.log('without moment', dateTesting3)
The result from the code above is:
now in UTC 2019-01-09T17:16:25Z
dateTesting2 ------- 01-09-2019 17:16:25
without moment 2019-01-09T17:16:25Z
I want the date to appear the same as in my computer (-6 hours)
You could force the issue with something like
`moment.utc(dateTesting).local().format('MM-DD-YYYY HH:mm:ss').subtract(6, 'hours)`
If you know your TIME_ZONE (sure), you can use:
const TIME_ZONE = -6;
const now = new Date(dateTesting);
now.setHours(now.getHours + TIME_ZONE) // or now.setMinutes(now.getMinutes()+ 60 * TIME_ZONE))
// because sometime TIME_ZONE is not `int`, example 4.5, 5.5, v.v,
//use with variable now, it's time same your time
If you run anywhere, you can get UTC time and convert it to your time, or you can use getTimezoneOffset:
const TIME_OFFSET = 360; // TIME_OFFSET = TIME_ZONE * 60
const now = new Date(time_of_any_where);
const thatOffset = now.getTimezoneOffset();
now.setMinutes(now.getMinutes+ thatOffset - TIME_OFFSET)
// Do something with `now`

Get timezone offset from timezone name using Javascript

I found many solution that gives Timezone name from offset value. But I have Timezone name and I want offset value for that. I tried setTimezone('Asia/Kolkata'), but I think their is no method like setTimezone.
example:
Asia/Kolkata should give me -330 ( offset )
This has got the be the easiest way to accomplish this task with modern JavaScript.
Note: Keep in mind that the offset is dependent on whether Daylight Savings Time (DST) is active.
/* #return A timezone offset in minutes */
const getOffset = (timeZone = 'UTC', date = new Date()) => {
const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
const tzDate = new Date(date.toLocaleString('en-US', { timeZone }));
return (tzDate.getTime() - utcDate.getTime()) / 6e4;
}
console.log(`No arguments: ${getOffset()}`); // 0
{
console.log('! Test Case #1 >> Now');
console.log(`Asia/Colombo : ${getOffset('Asia/Colombo')}`); // 330
console.log(`America/New_York : ${getOffset('America/New_York')}`); // -240
}
{
console.log('! Test Case #2 >> DST : off');
const date = new Date(2021, 0, 1);
console.log(`Asia/Colombo : ${getOffset('Asia/Colombo', date)}`); // 330
console.log(`America/New_York : ${getOffset('America/New_York', date)}`); // -300
}
{
console.log('! Test Case #3 >> DST : on');
const date = new Date(2021, 5, 1);
console.log(`Asia/Colombo : ${getOffset('Asia/Colombo', date)}`); // 330
console.log(`America/New_York : ${getOffset('America/New_York', date)}`); // -240
}
.as-console-wrapper { top: 0; max-height: 100% !important; }
I came across this same issue, and this is the solution I came up with, if you can get an IANA tz database name like the one you mentioned:
const myTimezoneName = "Asia/Colombo";
// Generating the formatted text
// Setting the timeZoneName to longOffset will convert PDT to GMT-07:00
const options = {timeZone: myTimezoneName, timeZoneName: "longOffset"};
const dateText = Intl.DateTimeFormat([], options).format(new Date);
// Scraping the numbers we want from the text
// The default value '+0' is needed when the timezone is missing the number part. Ex. Africa/Bamako --> GMT
let timezoneString = dateText.split(" ")[1].slice(3) || '+0';
// Getting the offset
let timezoneOffset = parseInt(timezoneString.split(':')[0])*60;
// Checking for a minutes offset and adding if appropriate
if (timezoneString.includes(":")) {
timezoneOffset = timezoneOffset + parseInt(timezoneString.split(':')[1]);
}
It's not a very nice solution, but it does the job without importing anything. It relies on the output format of the Intl.DateTimeFormat being consistent, which it should be, but that's a potential caveat.
You can't get it by name alone. You would also need to know the specific time. Asia/Kolkata may be fixed to a single offset, but many time zones alternate between standard time and daylight saving time, so you can't just get the offset, you can only get an offset.
For how to do it in JavaScript, see this answer.
Using countries and timezones npm package:
import {getTimezone} from 'countries-and-timezones';
const australianTimezone = 'Australia/Melbourne';
console.log(getTimezone(australianTimezone));
Prints to the console:
{
name: 'Australia/Melbourne',
country: 'AU',
utcOffset: 600,
utcOffsetStr: '+10:00',
dstOffset: 660,
dstOffsetStr: '+11:00',
aliasOf: null
}
From there, you can use the utcOffset or dstOffset depending on if it is daylight savings time.

How to the get the beginning of day of a date in javascript -- factoring in timezone

I am struggling to find out the beginning of day factoring in timezones in javascript. Consider the following:
var raw_time = new Date(this.created_at);
var offset_time = new Date(raw_hour.getTime() + time_zone_offset_in_ms);
// This resets timezone to server timezone
var offset_day = new Date(offset_time.setHours(0,0,0,0))
// always returns 2011-12-08 05:00:00 UTC, no matter what the offset was!
// This has the same issue:
var another_approach_offset_day = new Date(offset_time.getFullYear(),offset_time.getMonth(),offset_time.getHours())
I expect when i pass a Pacific Timezone offset, to get: 2011-12-08 08:00:00 UTC and so on.
What is the correct way to achieve this?
I think that part of the issue is that setHours method sets the hour (from 0 to 23), according to local time.
Also note that I am using javascript embedded in mongo, so I am unable to use any additional libraries.
Thanks!
Jeez, so this was really hard for me, but here is the final solution that I came up with the following solution. The trick was I need to use setHours or SetUTCHours to get the beginning of a day -- the only choices I have are system time and UTC. So I get the beginning of a UTC day, then add back the offset!
// Goal is given a time and a timezone, find the beginning of day
function(timestamp,selected_timezone_offset) {
var raw_time = new Date(timestamp)
var offset_time = new Date(raw_time.getTime() + selected_timezone_offset);
offset_time.setUTCHours(0,0,0,0);
var beginning_of_day = new Date(offset_time.getTime() - selected_timezone_offset);
return beginning_of_day;
}
In JavaScript all dates are stored as UTC. That is, the serial number returned by date.valueOf() is the number of milliseconds since 1970-01-01 00:00:00 UTC. But, when you examine a date via .toString() or .getHours(), etc., you get the value in local time. That is, the local time of the system running the script. You can get the value in UTC with methods like .toUTCString() or .getUTCHours(), etc.
So, you can't get a date in an arbitrary timezone, it's all UTC (or local). But, of course, you can get a string representation of a date in whatever timezone you like if you know the UTC offset. The easiest way would be to subtract the UTC offset from the date and call .getUTCHours() or .toUTCString() or whatever you need:
var d = new Date();
d.setMinutes(d.getMinutes() - 480); // get pacific standard time
d.toUTCString(); // returns "Fri, 9 Dec 2011 12:56:53 UTC"
Of course, you'll need to ignore that "UTC" at the end if you use .toUTCString(). You could just go:
d.toUTCString().replace(/UTC$/, "PST");
Edit: Don't worry about when timezones overlap date boundaries. If you pass setHours() a negative number, it will subtract those hours from midnight yesterday. Eg:
var d = new Date(2011, 11, 10, 15); // d represents Dec 10, 2011 at 3pm local time
d.setHours(-1); // d represents Dec 9, 2011 at 11pm local time
d.setHours(-24); // d represents Dec 8, 2011 at 12am local time
d.setHours(52); // d represents Dec 10, 2011 at 4am local time
Where does the time_zone_offset_in_ms variable you use come from? Perhaps it is unreliable, and you should be using Date's getTimezoneOffset() method. There is an example at the following URL:
http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp
If you know the date from a different date string you can do the following:
var currentDate = new Date(this.$picker.data('date'));
var today = new Date();
today.setHours(0, -currentDate.getTimezoneOffset(), 0, 0);
(based on the codebase for a project I did)
var aDate = new Date();
var startOfTheDay = new Date(aDate.getTime() - aDate.getTime() % 86400000)
Will create the beginning of the day, of the day in question
You can make use of Intl.DateTimeFormat. This is also how luxon handles timezones.
The code below can convert any date with any timezone to its beginging/end of the time.
const beginingOfDay = (options = {}) => {
const { date = new Date(), timeZone } = options;
const parts = Intl.DateTimeFormat("en-US", {
timeZone,
hourCycle: "h23",
hour: "numeric",
minute: "numeric",
second: "numeric",
}).formatToParts(date);
const hour = parseInt(parts.find((i) => i.type === "hour").value);
const minute = parseInt(parts.find((i) => i.type === "minute").value);
const second = parseInt(parts.find((i) => i.type === "second").value);
return new Date(
1000 *
Math.floor(
(date - hour * 3600000 - minute * 60000 - second * 1000) / 1000
)
);
};
const endOfDay = (...args) =>
new Date(beginingOfDay(...args).getTime() + 86399999);
const beginingOfYear = () => {};
console.log(beginingOfDay({ timeZone: "GMT" }));
console.log(endOfDay({ timeZone: "GMT" }));
console.log(beginingOfDay({ timeZone: "Asia/Tokyo" }));
console.log(endOfDay({ timeZone: "Asia/Tokyo" }));

Categories