Questions about Time Logic [duplicate] - javascript

Let's say user in CA, US picks up a date, time and timezone:
Worldwide beer marathon starts on 8/15/2013 10:00 am, UTC-08:00
Another user, in Central Europe opens the page where this date and time is displayed. He doesn't want to do time calculations (had few beers already). He just wants to see this date and time:
8/15/2013 19:00
Given the browser receives the date and time information, as entered by user in California:
Is there a way, in javascript, without external web services, to do a correct conversion? That is, to detect that 10am UTC-08:00 should actually be 10am UTC-07:00, since it is Daylight Saving.
Maybe I got wrong understanding of this from the beginning, but I don't want to let the entering user to think whether he should choose UTC-08:00 (PST) or UTC-07:00 (PDT). I assume that since the standard timezone in CA is PST, people don't switch to thinking in PDT in summer time. Or do they?!
In central Europe, standard date is UTC+01:00, Daylight Saving date is UTC+02:00. So that difference between CA and Europe should be 9 hours, except for two periods in a year, when one or the other area switches between Standard and Daylight Saving modes.
Update:
After some more thinking and reading the comments, what I would ideally need is this:
var utcOffset = f('2013-08-15T10:00', 'America/Los_Angeles');
// utcOffset == "-07:00"
var utcOffset = f('2013-11-15T10:00', 'America/Los_Angeles');
// utcOffset == "-08:00"
So far, it looks like the moment.js/timezone plugin, suggested by Guido Preite is capable of doing this (more or less).
Any other way, using browser APIs?

Is there a way, in javascript, without external web services, to do a correct conversion? That is, to detect that 10am UTC-08:00 should actually be 10am UTC-07:00, since it is Daylight Saving.
10:00-8 and 10:00-7 are two different moments in time. They are equal to 18:00Z and 17:00Z respectively (Z = UTC). When you are measuring in terms of an offset, daylight saving time does not enter the picture. Ever.
I assume that since the standard timezone in CA is PST, people don't switch to thinking in PDT in summer time. Or do they?!
In general, people just think in "Pacific Time", and that means both PST in the winter, and PDT in the summer. But computers are more precise. When you see PST, it means UTC-8. When you see PDT, it means UTC-7. It would be invalid to label using one form while simultaneously referring to the offset of the other.
Time zone abbreviations can be ambiguous. Ideally, when referencing the zone programmatically, you should use the IANA zone name, such as America/Los_Angeles. However, this is not currently possible in all JavaScript runtimes without a library. (They are working on this though.)
In central Europe, standard date is UTC+01:00, Daylight Saving date is UTC+02:00. So that difference between CA and Europe should be 9 hours, except for two periods in a year, when one or the other area switches between Standard and Daylight Saving modes.
Correct. They could be either 8, 9, or 10 hours apart. They switch at completely different times though, so don't try to manage this yourself.
So far, it looks like the moment.js/timezone plugin, suggested by Guido Preite is capable of doing this (more or less).
Moment-timezone is a great library. However, from the scenario you described, I don't think you need to worry about time zone conversion as much as you are thinking. See if you can follow this logic:
The user in California enters a date and time into a textbox.
You read that textbox value into a string, and parse it into a date:
var dt = new Date("8/15/2013 10:00");
or using moment.js:
var m = moment("8/15/2013 10:00", "M/D/YYYY HH:mm");
Because this is being done on the user's computer, JavaScript will automatically assume that this is a local date and time. You do not need to provide any offset or time zone information.
This does mean that because of the DST transitions that the time entered might be invalid or ambiguous. JavaScript doesn't do such a great job at handling that, in fact - you will get different results on different browsers. If you want to be unambiguous, then you would provide an offset.
// PST
var dt = new Date("3/11/2013 1:00 UTC-08:00");
// PDT
var dt = new Date("3/11/2013 1:00 UTC-07:00");
Once you have a Date (or a moment), then you can evaluate its UTC equivalent:
var s = dt.toISOString(); // 2013-08-15T17:00:00Z
it's the same with moment.js, but you will have better browser support:
var s = m.toISOString(); // 2013-08-15T17:00:00Z
You store that UTC value in your database.
The other user in Central Europe comes along and loads the data.
You feed it in to a Date or moment in JavaScript:
var dt = new Date("2013-08-15T17:00:00Z");
or with moment.js (again, better browser support)
var m = moment("2013-08-15T17:00:00Z")
Because JavaScript knows the time zone rules of the local computer, you can now display this date and it will be presented with the Central Europe time zone:
var s = dt.ToString(); // browser specific output
// ex: "Thu Aug 15 2013 19:00:00 GMT+0200 (Central Europe Daylight Time)"
or with moment.js, you can control the output format better
var s = m.format("DD/MM/YYYY HH:mm"); // "15/08/2013 19:00"
you could also let moment.js decide what localized format should be output:
var s = m.format("llll"); // "Thu, 15 Aug 2013 19:00"
To summarize - if you are only interested in converting to and from the local time zone (whatever zone that may be), then you can do it all with just Date. Moment.js will make things easier for parsing and formatting, but it isn't absolutely required.
There are only a few scenarios that require a time zone library (such as moment-timezone or others).
You want to convert to or from a zone that is not the local time zone or UTC.
You are working with dates that are in the past, and there has been a change to the time zone rules or daylight saving time rules since then, and you have dates that would be interpreted differently under the new rules than with the old ones. This is a bit technical, but it does happen. Read more here and here.

Default constructor creates instance of local time
var localDate = new Date();
I can't test it right now, but you should be able to provide your datetime (as a parameter to the constructor)..
var eventDate = [SOMEDATE];
var localDate = new Date(eventDate);
..and then you should be able to call Date object functions like getMonth, which returns data in local timezone. As written at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
Note1: Without server = there is no server|db at all? If there is, the date should be saved as UTC in db and load it as local time for every user.. that way you don't have to worry conversions.
Note2: This question has some code showing how to get timezone difference: How to get the exact local time of client?

I developed this solution based on other examples...hope this works for you! Available on jsfiddle.
/*
* Author: Mohammad M. AlBanna
* Website: MBanna.me
* Description: Get the current time in different time zone
*/
//Check daylight saving time prototype
Date.prototype.stdTimezoneOffset = function() {
var jan = new Date(this.getFullYear(), 0, 1);
var jul = new Date(this.getFullYear(), 6, 1);
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}
Date.prototype.dst = function() {
return this.getTimezoneOffset() < this.stdTimezoneOffset();
}
var today = new Date();
var isDST = today.dst() ? true : false;
var pstOffset = isDST ? 7 : 8;
var cstOffset = isDST ? 5 : 6;
var estOffset = isDST ? 4 : 5;
var gmtOffset = 1;
pstOffset = pstOffset * 60 * 60 * 1000;
cstOffset = cstOffset * 60 * 60 * 1000;
estOffset = estOffset * 60 * 60 * 1000;
gmtOffset = gmtOffset * 60 * 60 * 1000;
var todayMillis = today.getTime();
var timeZoneOffset = (today.getTimezoneOffset() * 60 * 1000);
var curretPST = todayMillis - pstOffset;
var curretCST = todayMillis - cstOffset;
var curretEST = todayMillis - estOffset;
var curretGMT = todayMillis - gmtOffset;
addP("PST Time : " + new Date(curretPST).toUTCString());
addP("CST Time : " + new Date(curretCST).toUTCString());
addP("EST Time : " + new Date(curretEST).toUTCString());
addP("GMT Time : " + new Date(curretGMT).toUTCString());
addP("Local Time : " + new Date(today.getTime() - timeZoneOffset ).toUTCString());
function addP(value){
var p = document.createElement("p");
p.innerHTML = value;
document.body.appendChild(p);
}

Related

How to manipulate timezone in a date object generated in nodejs [duplicate]

I have date time in a particular timezone as a string and I want to convert this to the local time. But, I don't know how to set the timezone in the Date object.
For example, I have Feb 28 2013 7:00 PM ET, then I can
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
As far as I know, I can either set the UTC time or local time. But, how do I set time in another timezone?
I tried to use the add/subtract the offset from UTC but I don't know how to counter daylight savings. Am not sure if I am heading the right direction.
How can I go about converting time from a different timezone to local time in javascript?
Background
JavaScript's Date object tracks time in UTC internally, but typically accepts input and produces output in the local time of the computer it's running on. It has very few facilities for working with time in other time zones.
The internal representation of a Date object is a single number, representing the number of milliseconds that have elapsed since 1970-01-01 00:00:00 UTC, without regard to leap seconds.
There is no time zone or string format stored in the Date object itself.
When various functions of the Date object are used, the computer's local time zone is applied to the internal representation. If the function produces a string, then the computer's locale information may be taken into consideration to determine how to produce that string. The details vary per function, and some are implementation-specific.
The only operations the Date object can do with non-local time zones are:
It can parse a string containing a numeric UTC offset from any time zone. It uses this to adjust the value being parsed, and stores the UTC equivalent. The original local time and offset are not retained in the resulting Date object. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toISOString() //=> "2020-04-12T16:00:00.000Z"
d.valueOf() //=> 1586707200000 (this is what is actually stored in the object)
In environments that have implemented the ECMASCript Internationalization API (aka "Intl"), a Date object can produce a locale-specific string adjusted to a given time zone identifier. This is accomplished via the timeZone option to toLocaleString and its variations. Most implementations will support IANA time zone identifiers, such as 'America/New_York'. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toLocaleString('en-US', { timeZone: 'America/New_York' })
//=> "4/12/2020, 12:00:00 PM"
// (midnight in China on Apring 13th is noon in New York on April 12th)
Most modern environments support the full set of IANA time zone identifiers (see the compatibility table here). However, keep in mind that the only identifier required to be supported by Intl is 'UTC', thus you should check carefully if you need to support older browsers or atypical environments (for example, lightweight IoT devices).
Libraries
There are several libraries that can be used to work with time zones. Though they still cannot make the Date object behave any differently, they typically implement the standard IANA timezone database and provide functions for using it in JavaScript. Modern libraries use the time zone data supplied by the Intl API, but older libraries typically have overhead, especially if you are running in a web browser, as the database can get a bit large. Some of these libraries also allow you to selectively reduce the data set, either by which time zones are supported and/or by the range of dates you can work with.
Here are the libraries to consider:
Intl-based Libraries
New development should choose from one of these implementations, which rely on the Intl API for their time zone data:
Luxon (successor of Moment.js)
date-fns-tz (extension for date-fns)
Day.js (when using its Timezone plugin)
Non-Intl Libraries
These libraries are maintained, but carry the burden of packaging their own time zone data, which can be quite large.
js-joda/timezone (extension for js-joda)
moment-timezone* (extension for Moment.js)
date-fns-timezone (extension for older 1.x of date-fns)
BigEasy/TimeZone
tz.js
* While Moment and Moment-Timezone were previously recommended, the Moment team now prefers users chose Luxon for new development.
Discontinued Libraries
These libraries have been officially discontinued and should no longer be used.
WallTime-js
TimeZoneJS
Future Proposals
The TC39 Temporal Proposal aims to provide a new set of standard objects for working with dates and times in the JavaScript language itself. This will include support for a time zone aware object.
Common Errors
There are several approaches that are often tried, which are in error and should usually be avoided.
Re-Parsing
new Date(new Date().toLocaleString('en', {timeZone: 'America/New_York'}))
The above approach correctly uses the Intl API to create a string in a specific time zone, but then it incorrectly passes that string back into the Date constructor. In this case, parsing will be implementation-specific, and may fail entirely. If successful, it is likely that the resulting Date object now represents the wrong instant in time, as the computer's local time zone would be applied during parsing.
Epoch Shifting
var d = new Date();
d.setTime(d.getTime() + someOffset * 60000);
The above approach attempts to manipulate the Date object's time zone by shifting the Unix timestamp by some other time zone offset. However, since the Date object only tracks time in UTC, it actually just makes the Date object represent a different point in time.
The same approach is sometimes used directly on the constructor, and is also invalid.
Epoch Shifting is sometimes used internally in date libraries as a shortcut to avoid writing calendar arithmetic. When doing so, any access to non-UTC properties must be avoided. For example, once shifted, a call to getUTCHours would be acceptable, but a call to getHours would be invalid because it uses the local time zone.
It is called "epoch shifting", because when used correctly, the Unix Epoch (1970-01-01T00:00:00.000Z) is now no longer correlated to a timestamp of 0 but has shifted to a different timestamp by the amount of the offset.
If you're not authoring a date library, you should not be epoch shifting.
For more details about epoch shifting, watch this video clip from Greg Miller at CppCon 2015. The video is about time_t in C++, but the explanation and problems are identical. (For JavaScript folks, every time you hear Greg mention time_t, just think "Date object".)
Trying to make a "UTC Date"
var d = new Date();
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()));
In this example, both d and utcDate are identical. The work to construct utcDate was redundant, because d is already in terms of UTC. Examining the output of toISOString, getTime, or valueOf functions will show identical values for both variables.
A similar approach seen is:
var d = new Date();
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
This is approach passes UTC values into the Date constructor where local time values are expected. The resulting Date object now represents a completely different point in time. It is essentially the same result as epoch shifting described earlier, and thus should be avoided.
The correct way to get a UTC-based Date object is simply new Date(). If you need a string representation that is in UTC, then use new Date().toISOString().
As Matt Johnson said
If you can limit your usage to modern web browsers, you can now do the
following without any special libraries:
new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
This isn't a comprehensive solution, but it works for many scenarios
that require only output conversion (from UTC or local time to a
specific time zone, but not the other direction).
So although the browser can not read IANA timezones when creating a date, or has any methods to change the timezones on an existing Date object, there seems to be a hack around it:
function changeTimezone(date, ianatz) {
// suppose the date is 12:00 UTC
var invdate = new Date(date.toLocaleString('en-US', {
timeZone: ianatz
}));
// then invdate will be 07:00 in Toronto
// and the diff is 5 hours
var diff = date.getTime() - invdate.getTime();
// so 12:00 in Toronto is 17:00 UTC
return new Date(date.getTime() - diff); // needs to substract
}
// E.g.
var here = new Date();
var there = changeTimezone(here, "America/Toronto");
console.log(`Here: ${here.toString()}\nToronto: ${there.toString()}`);
This should solve your problem, please feel free to offer fixes. This method will account also for daylight saving time for the given date.
dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
let date = new Date(Date.UTC(year, month, day, hour, minute, second));
let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
let offset = utcDate.getTime() - tzDate.getTime();
date.setTime( date.getTime() + offset );
return date;
};
How to use with timezone and local time:
dateWithTimeZone("America/Los_Angeles",2019,8,8,0,0,0)
You can specify a time zone offset on new Date(), for example:
new Date('Feb 28 2013 19:00:00 EST')
or
new Date('Feb 28 2013 19:00:00 GMT-0500')
Since Date store UTC time ( i.e. getTime returns in UTC ), javascript will them convert the time into UTC, and when you call things like toString javascript will convert the UTC time into browser's local timezone and return the string in local timezone, i.e. If I'm using UTC+8:
> new Date('Feb 28 2013 19:00:00 GMT-0500').toString()
< "Fri Mar 01 2013 08:00:00 GMT+0800 (CST)"
Also you can use normal getHours/Minute/Second method:
> new Date('Feb 28 2013 19:00:00 GMT-0500').getHours()
< 8
( This 8 means after the time is converted into my local time - UTC+8, the hours number is 8. )
I found the most supported way to do this, without worrying about a third party library, was by using getTimezoneOffset to calculate the appropriate timestamp, or update the time then use the normal methods to get the necessary date and time.
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
// ET timezone offset in hours.
var timezone = -5;
// Timezone offset in minutes + the desired offset in minutes, converted to ms.
// This offset should be the same for ALL date calculations, so you should only need to calculate it once.
var offset = (mydate.getTimezoneOffset() + (timezone * 60)) * 60 * 1000;
// Use the timestamp and offset as necessary to calculate min/sec etc, i.e. for countdowns.
var timestamp = mydate.getTime() + offset,
seconds = Math.floor(timestamp / 1000) % 60,
minutes = Math.floor(timestamp / 1000 / 60) % 60,
hours = Math.floor(timestamp / 1000 / 60 / 60);
// Or update the timestamp to reflect the timezone offset.
mydate.setTime(mydate.getTime() + offset);
// Then Output dates and times using the normal methods.
var date = mydate.getDate(),
hour = mydate.getHours();
EDIT
I was previously using UTC methods when performing the date transformations, which was incorrect. With adding the offset to the time, using the local get functions will return the desired results.
For Ionic users, I had hell with this because .toISOString() has to be used with the html template.
This will grab the current date, but of course can be added to previous answers for a selected date.
I got it fixed using this:
date = new Date();
public currentDate: any = new Date(this.date.getTime() - this.date.getTimezoneOffset()*60000).toISOString();
The *60000 is indicating the UTC -6 which is CST so whatever TimeZone is needed, the number and difference can be changed.
I ran into a similar problem with unit tests (specifically in jest when the unit tests run locally to create the snapshots and then the CI server runs in (potentially) a different timezone causing the snapshot comparison to fail). I mocked our Date and some of the supporting methods like so:
describe('...', () => {
let originalDate;
beforeEach(() => {
originalDate = Date;
Date = jest.fn(
(d) => {
let newD;
if (d) {
newD = (new originalDate(d));
} else {
newD = (new originalDate('2017-05-29T10:00:00z'));
}
newD.toLocaleString = () => {
return (new originalDate(newD.valueOf())).toLocaleString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleDateString = () => {
return (new originalDate(newD.valueOf())).toLocaleDateString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleTimeString = () => {
return (new originalDate(newD.valueOf())).toLocaleTimeString("en-US", {timeZone: "America/New_York"});
};
return newD;
}
);
Date.now = () => { return (Date()); };
});
afterEach(() => {
Date = originalDate;
});
});
I had the same problem but we can use the time zone we want
we use .toLocaleDateString()
eg:
var day=new Date();
const options= {day:'numeric', month:'long', year:"numeric", timeZone:"Asia/Kolkata"};
const today=day.toLocaleDateString("en-IN", options);
console.log(today);
I ran into this issue running a GCP Cloud Function. Of course it works on a local machine, but running in the cloud makes the OS default (local) for new Date() irrelevant. In my case, an api call from the cloud required Eastern Standard Time, in ISO format (without the "Z") with offset as "-0500" or "-0400" depending on DST, for example:
2021-12-01T00:00:00.000-0500
Again, this is not a browser formatting issue, so I am forced into this format for the api call to work correctly.
Using #chickens code as a start, this is what worked:
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
var dt = new Date(now_utc);
let utcDate = new Date(dt.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(dt.toLocaleString('en-US', { timeZone: "America/New_York" }));
let offset1 = utcDate.getTime() - tzDate.getTime();
let offset2 = offset1/60000;
let o1 = Math.abs(offset2);
console.log(offset2)
var offsetValue1 = (offset2 < 0 ? "+" : "-") + ("00" + Math.floor(o1 / 60)).slice(-2) + ("00" + (o1 % 60)).slice(-2);
console.log(offsetValue1)
dt.setTime(dt.getTime() - offset1);
console.log(dt.toISOString());
console.log(dt.toISOString().slice(0,-1)+offsetValue1);
Try using ctoc from npm.
https://www.npmjs.com/package/ctoc_timezone
It has got simple functionality to change timezones (most timezones around 400) and all custom formats u want it to display.
Building on the answers above, I am using this native one liner to convert the long timezone string to the three letter string:
var longTz = 'America/Los_Angeles';
var shortTz = new Date().
toLocaleString("en", {timeZoneName: "short", timeZone: longTz}).
split(' ').
pop();
This will give PDT or PST depending on the date provided. In my particular use case, developing on Salesforce (Aura/Lightning), we are able to get the user timezone in the long format from the backend.
Thanks to #commonpike answer, I wrote a function which takes an ISO String date such as 2020-10-10T08:00:00.000 as input and send an object which contains 2 main properties.
The first one is fromUtc is a Date corresponding to the timeZone entered as parameter.
The second one is toUtc which lets you to format a Date stemming from fromUtc.
const timeZoneTransformer = (stringDate, timeZone = "Europe/Paris") => {
const now = new Date();
const serverDate = new Date(stringDate);
const utcDate = new Date(
Date.UTC(
serverDate.getFullYear(),
serverDate.getMonth(),
serverDate.getDate(),
serverDate.getHours(),
serverDate.getMinutes(),
serverDate.getSeconds()
)
);
const invdate = new Date(
serverDate.toLocaleString("en-US", {
timeZone,
})
);
const diff = now.getTime() - invdate.getTime();
const adjustedDate = new Date(now.getTime() - diff);
return {
toUtc: utcDate,
fromUtc: adjustedDate,
};
};
const fromUtc = timeZoneTransformer("2020-10-10T08:00:00.000").fromUtc;
console.log(fromUtc);
const toUtc = timeZoneTransformer(fromUtc).toUtc;
console.log(toUtc);
Try: date-from-timezone, it resolves expected date with help of natively available Intl.DateTimeFormat.
I used that method in one of my projects for few years already, but it's now I decided to publish it as small OS project :)
Try something like this,
public static getTimezoneOffset(timeZone: string, date = new Date()): number {
const localDate = date.toLocaleString('fr', { timeZone, timeZoneName: 'long' });
const tz = localDate.split(' ');
const TZ = localDate.replace(tz[0], '').replace(tz[1], '').replace(' ', '');
const dateString = date.toString();
const offset = (Date.parse(`${dateString} UTC`) - Date.parse(`${dateString}${TZ}`)) / (3600 * 1000);
return offset;
}
I'm not sure why all these answers are so complicated. Just use YYYY-MM-DD ZZZ when creating a date-only date in the local / desired time zone.
Create a local date:
var myDate = new Date('2022-11-29 CST')
The date will be stored in storage as UTC, great.
Get the date out of storage and display it as local:
myDate.toLocaleDateString()
11/29/2022
I know its 3 years too late, but maybe it can help someone else because I haven't found anything like that except for the moment-timezone library, which is not exactly the same as what he's asking for here.
I've done something similar for german timezone,
this is a little complex because of daylight saving time and leap years where you have 366 days.
it might need a little work with the "isDaylightSavingTimeInGermany" function while different timezones change on different times the daylight saving time.
anyway, check out this page:
https://github.com/zerkotin/german-timezone-converter/wiki
the main methods are:
convertLocalDateToGermanTimezone
convertGermanDateToLocalTimezone
I've put an effort into documenting it, so it won't be so confusing.
There are several working answers here, but somehow a lot of them seemed to get you to the string, but not back to a date object you started with, so here's my simple non-function take on how to change timezone on JS date:
var TZ='Australia/Brisbane'; //Target timezone from server
var date = new Date(); //Init this to a time if you don't want current time
date=new Date(Date.parse(date.toLocaleString("en-US", {timeZone: TZ})));
//Just a clarification on what happens
// 1) First new Date() gives you a Date object at current time in the clients browser local timezone
// 2) .toLocaleString takes that time, and returns a string if time in the target timezone
// 3) Date.parse converts that new string to a Unix epoch number
// 4) new Date() converts the Unix epoch into a Date object in the new TimeZone.
// Now I can use my usual getHours and other Date functions as required.
Hope that helps others (if you get to this bottom answer!)
Simple with Node.JS support
Pass in the amount of hours your timezone is offset from UTC
function initDateInTimezone(offsetHours) {
const timezoneOffsetInMS = offsetHours * 60 * 60000;
let d = new Date().getTimezoneOffset() * 60000 + timezoneOffsetInMS;
const date = new Date(new Date().getTime() - d);
return date
}
//For Mumbai time difference is 5.5 hrs so
city_time_diff=5.5; //change according to your city
let time_now = Date.now();
time_now = time_now + (3600000 * city_time_diff); //Add our city time (in msec);
let new_date = new Date(time_now);
console.log("My city time is: ", new_date);
Was facing the same issue, used this one
Console.log(Date.parse("Jun 13, 2018 10:50:39 GMT+1"));
It will return milliseconds to which u can check have +100 timzone intialize British time
Hope it helps!!

How to set date in javascript with a different timezone than the system timezone? [duplicate]

I have date time in a particular timezone as a string and I want to convert this to the local time. But, I don't know how to set the timezone in the Date object.
For example, I have Feb 28 2013 7:00 PM ET, then I can
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
As far as I know, I can either set the UTC time or local time. But, how do I set time in another timezone?
I tried to use the add/subtract the offset from UTC but I don't know how to counter daylight savings. Am not sure if I am heading the right direction.
How can I go about converting time from a different timezone to local time in javascript?
Background
JavaScript's Date object tracks time in UTC internally, but typically accepts input and produces output in the local time of the computer it's running on. It has very few facilities for working with time in other time zones.
The internal representation of a Date object is a single number, representing the number of milliseconds that have elapsed since 1970-01-01 00:00:00 UTC, without regard to leap seconds.
There is no time zone or string format stored in the Date object itself.
When various functions of the Date object are used, the computer's local time zone is applied to the internal representation. If the function produces a string, then the computer's locale information may be taken into consideration to determine how to produce that string. The details vary per function, and some are implementation-specific.
The only operations the Date object can do with non-local time zones are:
It can parse a string containing a numeric UTC offset from any time zone. It uses this to adjust the value being parsed, and stores the UTC equivalent. The original local time and offset are not retained in the resulting Date object. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toISOString() //=> "2020-04-12T16:00:00.000Z"
d.valueOf() //=> 1586707200000 (this is what is actually stored in the object)
In environments that have implemented the ECMASCript Internationalization API (aka "Intl"), a Date object can produce a locale-specific string adjusted to a given time zone identifier. This is accomplished via the timeZone option to toLocaleString and its variations. Most implementations will support IANA time zone identifiers, such as 'America/New_York'. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toLocaleString('en-US', { timeZone: 'America/New_York' })
//=> "4/12/2020, 12:00:00 PM"
// (midnight in China on Apring 13th is noon in New York on April 12th)
Most modern environments support the full set of IANA time zone identifiers (see the compatibility table here). However, keep in mind that the only identifier required to be supported by Intl is 'UTC', thus you should check carefully if you need to support older browsers or atypical environments (for example, lightweight IoT devices).
Libraries
There are several libraries that can be used to work with time zones. Though they still cannot make the Date object behave any differently, they typically implement the standard IANA timezone database and provide functions for using it in JavaScript. Modern libraries use the time zone data supplied by the Intl API, but older libraries typically have overhead, especially if you are running in a web browser, as the database can get a bit large. Some of these libraries also allow you to selectively reduce the data set, either by which time zones are supported and/or by the range of dates you can work with.
Here are the libraries to consider:
Intl-based Libraries
New development should choose from one of these implementations, which rely on the Intl API for their time zone data:
Luxon (successor of Moment.js)
date-fns-tz (extension for date-fns)
Day.js (when using its Timezone plugin)
Non-Intl Libraries
These libraries are maintained, but carry the burden of packaging their own time zone data, which can be quite large.
js-joda/timezone (extension for js-joda)
moment-timezone* (extension for Moment.js)
date-fns-timezone (extension for older 1.x of date-fns)
BigEasy/TimeZone
tz.js
* While Moment and Moment-Timezone were previously recommended, the Moment team now prefers users chose Luxon for new development.
Discontinued Libraries
These libraries have been officially discontinued and should no longer be used.
WallTime-js
TimeZoneJS
Future Proposals
The TC39 Temporal Proposal aims to provide a new set of standard objects for working with dates and times in the JavaScript language itself. This will include support for a time zone aware object.
Common Errors
There are several approaches that are often tried, which are in error and should usually be avoided.
Re-Parsing
new Date(new Date().toLocaleString('en', {timeZone: 'America/New_York'}))
The above approach correctly uses the Intl API to create a string in a specific time zone, but then it incorrectly passes that string back into the Date constructor. In this case, parsing will be implementation-specific, and may fail entirely. If successful, it is likely that the resulting Date object now represents the wrong instant in time, as the computer's local time zone would be applied during parsing.
Epoch Shifting
var d = new Date();
d.setTime(d.getTime() + someOffset * 60000);
The above approach attempts to manipulate the Date object's time zone by shifting the Unix timestamp by some other time zone offset. However, since the Date object only tracks time in UTC, it actually just makes the Date object represent a different point in time.
The same approach is sometimes used directly on the constructor, and is also invalid.
Epoch Shifting is sometimes used internally in date libraries as a shortcut to avoid writing calendar arithmetic. When doing so, any access to non-UTC properties must be avoided. For example, once shifted, a call to getUTCHours would be acceptable, but a call to getHours would be invalid because it uses the local time zone.
It is called "epoch shifting", because when used correctly, the Unix Epoch (1970-01-01T00:00:00.000Z) is now no longer correlated to a timestamp of 0 but has shifted to a different timestamp by the amount of the offset.
If you're not authoring a date library, you should not be epoch shifting.
For more details about epoch shifting, watch this video clip from Greg Miller at CppCon 2015. The video is about time_t in C++, but the explanation and problems are identical. (For JavaScript folks, every time you hear Greg mention time_t, just think "Date object".)
Trying to make a "UTC Date"
var d = new Date();
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()));
In this example, both d and utcDate are identical. The work to construct utcDate was redundant, because d is already in terms of UTC. Examining the output of toISOString, getTime, or valueOf functions will show identical values for both variables.
A similar approach seen is:
var d = new Date();
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
This is approach passes UTC values into the Date constructor where local time values are expected. The resulting Date object now represents a completely different point in time. It is essentially the same result as epoch shifting described earlier, and thus should be avoided.
The correct way to get a UTC-based Date object is simply new Date(). If you need a string representation that is in UTC, then use new Date().toISOString().
As Matt Johnson said
If you can limit your usage to modern web browsers, you can now do the
following without any special libraries:
new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
This isn't a comprehensive solution, but it works for many scenarios
that require only output conversion (from UTC or local time to a
specific time zone, but not the other direction).
So although the browser can not read IANA timezones when creating a date, or has any methods to change the timezones on an existing Date object, there seems to be a hack around it:
function changeTimezone(date, ianatz) {
// suppose the date is 12:00 UTC
var invdate = new Date(date.toLocaleString('en-US', {
timeZone: ianatz
}));
// then invdate will be 07:00 in Toronto
// and the diff is 5 hours
var diff = date.getTime() - invdate.getTime();
// so 12:00 in Toronto is 17:00 UTC
return new Date(date.getTime() - diff); // needs to substract
}
// E.g.
var here = new Date();
var there = changeTimezone(here, "America/Toronto");
console.log(`Here: ${here.toString()}\nToronto: ${there.toString()}`);
This should solve your problem, please feel free to offer fixes. This method will account also for daylight saving time for the given date.
dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
let date = new Date(Date.UTC(year, month, day, hour, minute, second));
let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
let offset = utcDate.getTime() - tzDate.getTime();
date.setTime( date.getTime() + offset );
return date;
};
How to use with timezone and local time:
dateWithTimeZone("America/Los_Angeles",2019,8,8,0,0,0)
You can specify a time zone offset on new Date(), for example:
new Date('Feb 28 2013 19:00:00 EST')
or
new Date('Feb 28 2013 19:00:00 GMT-0500')
Since Date store UTC time ( i.e. getTime returns in UTC ), javascript will them convert the time into UTC, and when you call things like toString javascript will convert the UTC time into browser's local timezone and return the string in local timezone, i.e. If I'm using UTC+8:
> new Date('Feb 28 2013 19:00:00 GMT-0500').toString()
< "Fri Mar 01 2013 08:00:00 GMT+0800 (CST)"
Also you can use normal getHours/Minute/Second method:
> new Date('Feb 28 2013 19:00:00 GMT-0500').getHours()
< 8
( This 8 means after the time is converted into my local time - UTC+8, the hours number is 8. )
I found the most supported way to do this, without worrying about a third party library, was by using getTimezoneOffset to calculate the appropriate timestamp, or update the time then use the normal methods to get the necessary date and time.
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
// ET timezone offset in hours.
var timezone = -5;
// Timezone offset in minutes + the desired offset in minutes, converted to ms.
// This offset should be the same for ALL date calculations, so you should only need to calculate it once.
var offset = (mydate.getTimezoneOffset() + (timezone * 60)) * 60 * 1000;
// Use the timestamp and offset as necessary to calculate min/sec etc, i.e. for countdowns.
var timestamp = mydate.getTime() + offset,
seconds = Math.floor(timestamp / 1000) % 60,
minutes = Math.floor(timestamp / 1000 / 60) % 60,
hours = Math.floor(timestamp / 1000 / 60 / 60);
// Or update the timestamp to reflect the timezone offset.
mydate.setTime(mydate.getTime() + offset);
// Then Output dates and times using the normal methods.
var date = mydate.getDate(),
hour = mydate.getHours();
EDIT
I was previously using UTC methods when performing the date transformations, which was incorrect. With adding the offset to the time, using the local get functions will return the desired results.
For Ionic users, I had hell with this because .toISOString() has to be used with the html template.
This will grab the current date, but of course can be added to previous answers for a selected date.
I got it fixed using this:
date = new Date();
public currentDate: any = new Date(this.date.getTime() - this.date.getTimezoneOffset()*60000).toISOString();
The *60000 is indicating the UTC -6 which is CST so whatever TimeZone is needed, the number and difference can be changed.
I ran into a similar problem with unit tests (specifically in jest when the unit tests run locally to create the snapshots and then the CI server runs in (potentially) a different timezone causing the snapshot comparison to fail). I mocked our Date and some of the supporting methods like so:
describe('...', () => {
let originalDate;
beforeEach(() => {
originalDate = Date;
Date = jest.fn(
(d) => {
let newD;
if (d) {
newD = (new originalDate(d));
} else {
newD = (new originalDate('2017-05-29T10:00:00z'));
}
newD.toLocaleString = () => {
return (new originalDate(newD.valueOf())).toLocaleString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleDateString = () => {
return (new originalDate(newD.valueOf())).toLocaleDateString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleTimeString = () => {
return (new originalDate(newD.valueOf())).toLocaleTimeString("en-US", {timeZone: "America/New_York"});
};
return newD;
}
);
Date.now = () => { return (Date()); };
});
afterEach(() => {
Date = originalDate;
});
});
I had the same problem but we can use the time zone we want
we use .toLocaleDateString()
eg:
var day=new Date();
const options= {day:'numeric', month:'long', year:"numeric", timeZone:"Asia/Kolkata"};
const today=day.toLocaleDateString("en-IN", options);
console.log(today);
I ran into this issue running a GCP Cloud Function. Of course it works on a local machine, but running in the cloud makes the OS default (local) for new Date() irrelevant. In my case, an api call from the cloud required Eastern Standard Time, in ISO format (without the "Z") with offset as "-0500" or "-0400" depending on DST, for example:
2021-12-01T00:00:00.000-0500
Again, this is not a browser formatting issue, so I am forced into this format for the api call to work correctly.
Using #chickens code as a start, this is what worked:
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
var dt = new Date(now_utc);
let utcDate = new Date(dt.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(dt.toLocaleString('en-US', { timeZone: "America/New_York" }));
let offset1 = utcDate.getTime() - tzDate.getTime();
let offset2 = offset1/60000;
let o1 = Math.abs(offset2);
console.log(offset2)
var offsetValue1 = (offset2 < 0 ? "+" : "-") + ("00" + Math.floor(o1 / 60)).slice(-2) + ("00" + (o1 % 60)).slice(-2);
console.log(offsetValue1)
dt.setTime(dt.getTime() - offset1);
console.log(dt.toISOString());
console.log(dt.toISOString().slice(0,-1)+offsetValue1);
Try using ctoc from npm.
https://www.npmjs.com/package/ctoc_timezone
It has got simple functionality to change timezones (most timezones around 400) and all custom formats u want it to display.
Building on the answers above, I am using this native one liner to convert the long timezone string to the three letter string:
var longTz = 'America/Los_Angeles';
var shortTz = new Date().
toLocaleString("en", {timeZoneName: "short", timeZone: longTz}).
split(' ').
pop();
This will give PDT or PST depending on the date provided. In my particular use case, developing on Salesforce (Aura/Lightning), we are able to get the user timezone in the long format from the backend.
Thanks to #commonpike answer, I wrote a function which takes an ISO String date such as 2020-10-10T08:00:00.000 as input and send an object which contains 2 main properties.
The first one is fromUtc is a Date corresponding to the timeZone entered as parameter.
The second one is toUtc which lets you to format a Date stemming from fromUtc.
const timeZoneTransformer = (stringDate, timeZone = "Europe/Paris") => {
const now = new Date();
const serverDate = new Date(stringDate);
const utcDate = new Date(
Date.UTC(
serverDate.getFullYear(),
serverDate.getMonth(),
serverDate.getDate(),
serverDate.getHours(),
serverDate.getMinutes(),
serverDate.getSeconds()
)
);
const invdate = new Date(
serverDate.toLocaleString("en-US", {
timeZone,
})
);
const diff = now.getTime() - invdate.getTime();
const adjustedDate = new Date(now.getTime() - diff);
return {
toUtc: utcDate,
fromUtc: adjustedDate,
};
};
const fromUtc = timeZoneTransformer("2020-10-10T08:00:00.000").fromUtc;
console.log(fromUtc);
const toUtc = timeZoneTransformer(fromUtc).toUtc;
console.log(toUtc);
Try: date-from-timezone, it resolves expected date with help of natively available Intl.DateTimeFormat.
I used that method in one of my projects for few years already, but it's now I decided to publish it as small OS project :)
Try something like this,
public static getTimezoneOffset(timeZone: string, date = new Date()): number {
const localDate = date.toLocaleString('fr', { timeZone, timeZoneName: 'long' });
const tz = localDate.split(' ');
const TZ = localDate.replace(tz[0], '').replace(tz[1], '').replace(' ', '');
const dateString = date.toString();
const offset = (Date.parse(`${dateString} UTC`) - Date.parse(`${dateString}${TZ}`)) / (3600 * 1000);
return offset;
}
I'm not sure why all these answers are so complicated. Just use YYYY-MM-DD ZZZ when creating a date-only date in the local / desired time zone.
Create a local date:
var myDate = new Date('2022-11-29 CST')
The date will be stored in storage as UTC, great.
Get the date out of storage and display it as local:
myDate.toLocaleDateString()
11/29/2022
I know its 3 years too late, but maybe it can help someone else because I haven't found anything like that except for the moment-timezone library, which is not exactly the same as what he's asking for here.
I've done something similar for german timezone,
this is a little complex because of daylight saving time and leap years where you have 366 days.
it might need a little work with the "isDaylightSavingTimeInGermany" function while different timezones change on different times the daylight saving time.
anyway, check out this page:
https://github.com/zerkotin/german-timezone-converter/wiki
the main methods are:
convertLocalDateToGermanTimezone
convertGermanDateToLocalTimezone
I've put an effort into documenting it, so it won't be so confusing.
There are several working answers here, but somehow a lot of them seemed to get you to the string, but not back to a date object you started with, so here's my simple non-function take on how to change timezone on JS date:
var TZ='Australia/Brisbane'; //Target timezone from server
var date = new Date(); //Init this to a time if you don't want current time
date=new Date(Date.parse(date.toLocaleString("en-US", {timeZone: TZ})));
//Just a clarification on what happens
// 1) First new Date() gives you a Date object at current time in the clients browser local timezone
// 2) .toLocaleString takes that time, and returns a string if time in the target timezone
// 3) Date.parse converts that new string to a Unix epoch number
// 4) new Date() converts the Unix epoch into a Date object in the new TimeZone.
// Now I can use my usual getHours and other Date functions as required.
Hope that helps others (if you get to this bottom answer!)
Simple with Node.JS support
Pass in the amount of hours your timezone is offset from UTC
function initDateInTimezone(offsetHours) {
const timezoneOffsetInMS = offsetHours * 60 * 60000;
let d = new Date().getTimezoneOffset() * 60000 + timezoneOffsetInMS;
const date = new Date(new Date().getTime() - d);
return date
}
//For Mumbai time difference is 5.5 hrs so
city_time_diff=5.5; //change according to your city
let time_now = Date.now();
time_now = time_now + (3600000 * city_time_diff); //Add our city time (in msec);
let new_date = new Date(time_now);
console.log("My city time is: ", new_date);
Was facing the same issue, used this one
Console.log(Date.parse("Jun 13, 2018 10:50:39 GMT+1"));
It will return milliseconds to which u can check have +100 timzone intialize British time
Hope it helps!!

Store date + timezone in UTC [duplicate]

I have date time in a particular timezone as a string and I want to convert this to the local time. But, I don't know how to set the timezone in the Date object.
For example, I have Feb 28 2013 7:00 PM ET, then I can
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
As far as I know, I can either set the UTC time or local time. But, how do I set time in another timezone?
I tried to use the add/subtract the offset from UTC but I don't know how to counter daylight savings. Am not sure if I am heading the right direction.
How can I go about converting time from a different timezone to local time in javascript?
Background
JavaScript's Date object tracks time in UTC internally, but typically accepts input and produces output in the local time of the computer it's running on. It has very few facilities for working with time in other time zones.
The internal representation of a Date object is a single number, representing the number of milliseconds that have elapsed since 1970-01-01 00:00:00 UTC, without regard to leap seconds.
There is no time zone or string format stored in the Date object itself.
When various functions of the Date object are used, the computer's local time zone is applied to the internal representation. If the function produces a string, then the computer's locale information may be taken into consideration to determine how to produce that string. The details vary per function, and some are implementation-specific.
The only operations the Date object can do with non-local time zones are:
It can parse a string containing a numeric UTC offset from any time zone. It uses this to adjust the value being parsed, and stores the UTC equivalent. The original local time and offset are not retained in the resulting Date object. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toISOString() //=> "2020-04-12T16:00:00.000Z"
d.valueOf() //=> 1586707200000 (this is what is actually stored in the object)
In environments that have implemented the ECMASCript Internationalization API (aka "Intl"), a Date object can produce a locale-specific string adjusted to a given time zone identifier. This is accomplished via the timeZone option to toLocaleString and its variations. Most implementations will support IANA time zone identifiers, such as 'America/New_York'. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toLocaleString('en-US', { timeZone: 'America/New_York' })
//=> "4/12/2020, 12:00:00 PM"
// (midnight in China on Apring 13th is noon in New York on April 12th)
Most modern environments support the full set of IANA time zone identifiers (see the compatibility table here). However, keep in mind that the only identifier required to be supported by Intl is 'UTC', thus you should check carefully if you need to support older browsers or atypical environments (for example, lightweight IoT devices).
Libraries
There are several libraries that can be used to work with time zones. Though they still cannot make the Date object behave any differently, they typically implement the standard IANA timezone database and provide functions for using it in JavaScript. Modern libraries use the time zone data supplied by the Intl API, but older libraries typically have overhead, especially if you are running in a web browser, as the database can get a bit large. Some of these libraries also allow you to selectively reduce the data set, either by which time zones are supported and/or by the range of dates you can work with.
Here are the libraries to consider:
Intl-based Libraries
New development should choose from one of these implementations, which rely on the Intl API for their time zone data:
Luxon (successor of Moment.js)
date-fns-tz (extension for date-fns)
Day.js (when using its Timezone plugin)
Non-Intl Libraries
These libraries are maintained, but carry the burden of packaging their own time zone data, which can be quite large.
js-joda/timezone (extension for js-joda)
moment-timezone* (extension for Moment.js)
date-fns-timezone (extension for older 1.x of date-fns)
BigEasy/TimeZone
tz.js
* While Moment and Moment-Timezone were previously recommended, the Moment team now prefers users chose Luxon for new development.
Discontinued Libraries
These libraries have been officially discontinued and should no longer be used.
WallTime-js
TimeZoneJS
Future Proposals
The TC39 Temporal Proposal aims to provide a new set of standard objects for working with dates and times in the JavaScript language itself. This will include support for a time zone aware object.
Common Errors
There are several approaches that are often tried, which are in error and should usually be avoided.
Re-Parsing
new Date(new Date().toLocaleString('en', {timeZone: 'America/New_York'}))
The above approach correctly uses the Intl API to create a string in a specific time zone, but then it incorrectly passes that string back into the Date constructor. In this case, parsing will be implementation-specific, and may fail entirely. If successful, it is likely that the resulting Date object now represents the wrong instant in time, as the computer's local time zone would be applied during parsing.
Epoch Shifting
var d = new Date();
d.setTime(d.getTime() + someOffset * 60000);
The above approach attempts to manipulate the Date object's time zone by shifting the Unix timestamp by some other time zone offset. However, since the Date object only tracks time in UTC, it actually just makes the Date object represent a different point in time.
The same approach is sometimes used directly on the constructor, and is also invalid.
Epoch Shifting is sometimes used internally in date libraries as a shortcut to avoid writing calendar arithmetic. When doing so, any access to non-UTC properties must be avoided. For example, once shifted, a call to getUTCHours would be acceptable, but a call to getHours would be invalid because it uses the local time zone.
It is called "epoch shifting", because when used correctly, the Unix Epoch (1970-01-01T00:00:00.000Z) is now no longer correlated to a timestamp of 0 but has shifted to a different timestamp by the amount of the offset.
If you're not authoring a date library, you should not be epoch shifting.
For more details about epoch shifting, watch this video clip from Greg Miller at CppCon 2015. The video is about time_t in C++, but the explanation and problems are identical. (For JavaScript folks, every time you hear Greg mention time_t, just think "Date object".)
Trying to make a "UTC Date"
var d = new Date();
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()));
In this example, both d and utcDate are identical. The work to construct utcDate was redundant, because d is already in terms of UTC. Examining the output of toISOString, getTime, or valueOf functions will show identical values for both variables.
A similar approach seen is:
var d = new Date();
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
This is approach passes UTC values into the Date constructor where local time values are expected. The resulting Date object now represents a completely different point in time. It is essentially the same result as epoch shifting described earlier, and thus should be avoided.
The correct way to get a UTC-based Date object is simply new Date(). If you need a string representation that is in UTC, then use new Date().toISOString().
As Matt Johnson said
If you can limit your usage to modern web browsers, you can now do the
following without any special libraries:
new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
This isn't a comprehensive solution, but it works for many scenarios
that require only output conversion (from UTC or local time to a
specific time zone, but not the other direction).
So although the browser can not read IANA timezones when creating a date, or has any methods to change the timezones on an existing Date object, there seems to be a hack around it:
function changeTimezone(date, ianatz) {
// suppose the date is 12:00 UTC
var invdate = new Date(date.toLocaleString('en-US', {
timeZone: ianatz
}));
// then invdate will be 07:00 in Toronto
// and the diff is 5 hours
var diff = date.getTime() - invdate.getTime();
// so 12:00 in Toronto is 17:00 UTC
return new Date(date.getTime() - diff); // needs to substract
}
// E.g.
var here = new Date();
var there = changeTimezone(here, "America/Toronto");
console.log(`Here: ${here.toString()}\nToronto: ${there.toString()}`);
This should solve your problem, please feel free to offer fixes. This method will account also for daylight saving time for the given date.
dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
let date = new Date(Date.UTC(year, month, day, hour, minute, second));
let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
let offset = utcDate.getTime() - tzDate.getTime();
date.setTime( date.getTime() + offset );
return date;
};
How to use with timezone and local time:
dateWithTimeZone("America/Los_Angeles",2019,8,8,0,0,0)
You can specify a time zone offset on new Date(), for example:
new Date('Feb 28 2013 19:00:00 EST')
or
new Date('Feb 28 2013 19:00:00 GMT-0500')
Since Date store UTC time ( i.e. getTime returns in UTC ), javascript will them convert the time into UTC, and when you call things like toString javascript will convert the UTC time into browser's local timezone and return the string in local timezone, i.e. If I'm using UTC+8:
> new Date('Feb 28 2013 19:00:00 GMT-0500').toString()
< "Fri Mar 01 2013 08:00:00 GMT+0800 (CST)"
Also you can use normal getHours/Minute/Second method:
> new Date('Feb 28 2013 19:00:00 GMT-0500').getHours()
< 8
( This 8 means after the time is converted into my local time - UTC+8, the hours number is 8. )
I found the most supported way to do this, without worrying about a third party library, was by using getTimezoneOffset to calculate the appropriate timestamp, or update the time then use the normal methods to get the necessary date and time.
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
// ET timezone offset in hours.
var timezone = -5;
// Timezone offset in minutes + the desired offset in minutes, converted to ms.
// This offset should be the same for ALL date calculations, so you should only need to calculate it once.
var offset = (mydate.getTimezoneOffset() + (timezone * 60)) * 60 * 1000;
// Use the timestamp and offset as necessary to calculate min/sec etc, i.e. for countdowns.
var timestamp = mydate.getTime() + offset,
seconds = Math.floor(timestamp / 1000) % 60,
minutes = Math.floor(timestamp / 1000 / 60) % 60,
hours = Math.floor(timestamp / 1000 / 60 / 60);
// Or update the timestamp to reflect the timezone offset.
mydate.setTime(mydate.getTime() + offset);
// Then Output dates and times using the normal methods.
var date = mydate.getDate(),
hour = mydate.getHours();
EDIT
I was previously using UTC methods when performing the date transformations, which was incorrect. With adding the offset to the time, using the local get functions will return the desired results.
For Ionic users, I had hell with this because .toISOString() has to be used with the html template.
This will grab the current date, but of course can be added to previous answers for a selected date.
I got it fixed using this:
date = new Date();
public currentDate: any = new Date(this.date.getTime() - this.date.getTimezoneOffset()*60000).toISOString();
The *60000 is indicating the UTC -6 which is CST so whatever TimeZone is needed, the number and difference can be changed.
I ran into this issue running a GCP Cloud Function. Of course it works on a local machine, but running in the cloud makes the OS default (local) for new Date() irrelevant. In my case, an api call from the cloud required Eastern Standard Time, in ISO format (without the "Z") with offset as "-0500" or "-0400" depending on DST, for example:
2021-12-01T00:00:00.000-0500
Again, this is not a browser formatting issue, so I am forced into this format for the api call to work correctly.
Using #chickens code as a start, this is what worked:
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
var dt = new Date(now_utc);
let utcDate = new Date(dt.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(dt.toLocaleString('en-US', { timeZone: "America/New_York" }));
let offset1 = utcDate.getTime() - tzDate.getTime();
let offset2 = offset1/60000;
let o1 = Math.abs(offset2);
console.log(offset2)
var offsetValue1 = (offset2 < 0 ? "+" : "-") + ("00" + Math.floor(o1 / 60)).slice(-2) + ("00" + (o1 % 60)).slice(-2);
console.log(offsetValue1)
dt.setTime(dt.getTime() - offset1);
console.log(dt.toISOString());
console.log(dt.toISOString().slice(0,-1)+offsetValue1);
I ran into a similar problem with unit tests (specifically in jest when the unit tests run locally to create the snapshots and then the CI server runs in (potentially) a different timezone causing the snapshot comparison to fail). I mocked our Date and some of the supporting methods like so:
describe('...', () => {
let originalDate;
beforeEach(() => {
originalDate = Date;
Date = jest.fn(
(d) => {
let newD;
if (d) {
newD = (new originalDate(d));
} else {
newD = (new originalDate('2017-05-29T10:00:00z'));
}
newD.toLocaleString = () => {
return (new originalDate(newD.valueOf())).toLocaleString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleDateString = () => {
return (new originalDate(newD.valueOf())).toLocaleDateString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleTimeString = () => {
return (new originalDate(newD.valueOf())).toLocaleTimeString("en-US", {timeZone: "America/New_York"});
};
return newD;
}
);
Date.now = () => { return (Date()); };
});
afterEach(() => {
Date = originalDate;
});
});
I had the same problem but we can use the time zone we want
we use .toLocaleDateString()
eg:
var day=new Date();
const options= {day:'numeric', month:'long', year:"numeric", timeZone:"Asia/Kolkata"};
const today=day.toLocaleDateString("en-IN", options);
console.log(today);
Try using ctoc from npm.
https://www.npmjs.com/package/ctoc_timezone
It has got simple functionality to change timezones (most timezones around 400) and all custom formats u want it to display.
Building on the answers above, I am using this native one liner to convert the long timezone string to the three letter string:
var longTz = 'America/Los_Angeles';
var shortTz = new Date().
toLocaleString("en", {timeZoneName: "short", timeZone: longTz}).
split(' ').
pop();
This will give PDT or PST depending on the date provided. In my particular use case, developing on Salesforce (Aura/Lightning), we are able to get the user timezone in the long format from the backend.
Thanks to #commonpike answer, I wrote a function which takes an ISO String date such as 2020-10-10T08:00:00.000 as input and send an object which contains 2 main properties.
The first one is fromUtc is a Date corresponding to the timeZone entered as parameter.
The second one is toUtc which lets you to format a Date stemming from fromUtc.
const timeZoneTransformer = (stringDate, timeZone = "Europe/Paris") => {
const now = new Date();
const serverDate = new Date(stringDate);
const utcDate = new Date(
Date.UTC(
serverDate.getFullYear(),
serverDate.getMonth(),
serverDate.getDate(),
serverDate.getHours(),
serverDate.getMinutes(),
serverDate.getSeconds()
)
);
const invdate = new Date(
serverDate.toLocaleString("en-US", {
timeZone,
})
);
const diff = now.getTime() - invdate.getTime();
const adjustedDate = new Date(now.getTime() - diff);
return {
toUtc: utcDate,
fromUtc: adjustedDate,
};
};
const fromUtc = timeZoneTransformer("2020-10-10T08:00:00.000").fromUtc;
console.log(fromUtc);
const toUtc = timeZoneTransformer(fromUtc).toUtc;
console.log(toUtc);
Try: date-from-timezone, it resolves expected date with help of natively available Intl.DateTimeFormat.
I used that method in one of my projects for few years already, but it's now I decided to publish it as small OS project :)
Try something like this,
public static getTimezoneOffset(timeZone: string, date = new Date()): number {
const localDate = date.toLocaleString('fr', { timeZone, timeZoneName: 'long' });
const tz = localDate.split(' ');
const TZ = localDate.replace(tz[0], '').replace(tz[1], '').replace(' ', '');
const dateString = date.toString();
const offset = (Date.parse(`${dateString} UTC`) - Date.parse(`${dateString}${TZ}`)) / (3600 * 1000);
return offset;
}
I'm not sure why all these answers are so complicated. Just use YYYY-MM-DD ZZZ when creating a date-only date in the local / desired time zone.
Create a local date:
var myDate = new Date('2022-11-29 CST')
The date will be stored in storage as UTC, great.
Get the date out of storage and display it as local:
myDate.toLocaleDateString()
11/29/2022
I know its 3 years too late, but maybe it can help someone else because I haven't found anything like that except for the moment-timezone library, which is not exactly the same as what he's asking for here.
I've done something similar for german timezone,
this is a little complex because of daylight saving time and leap years where you have 366 days.
it might need a little work with the "isDaylightSavingTimeInGermany" function while different timezones change on different times the daylight saving time.
anyway, check out this page:
https://github.com/zerkotin/german-timezone-converter/wiki
the main methods are:
convertLocalDateToGermanTimezone
convertGermanDateToLocalTimezone
I've put an effort into documenting it, so it won't be so confusing.
There are several working answers here, but somehow a lot of them seemed to get you to the string, but not back to a date object you started with, so here's my simple non-function take on how to change timezone on JS date:
var TZ='Australia/Brisbane'; //Target timezone from server
var date = new Date(); //Init this to a time if you don't want current time
date=new Date(Date.parse(date.toLocaleString("en-US", {timeZone: TZ})));
//Just a clarification on what happens
// 1) First new Date() gives you a Date object at current time in the clients browser local timezone
// 2) .toLocaleString takes that time, and returns a string if time in the target timezone
// 3) Date.parse converts that new string to a Unix epoch number
// 4) new Date() converts the Unix epoch into a Date object in the new TimeZone.
// Now I can use my usual getHours and other Date functions as required.
Hope that helps others (if you get to this bottom answer!)
Simple with Node.JS support
Pass in the amount of hours your timezone is offset from UTC
function initDateInTimezone(offsetHours) {
const timezoneOffsetInMS = offsetHours * 60 * 60000;
let d = new Date().getTimezoneOffset() * 60000 + timezoneOffsetInMS;
const date = new Date(new Date().getTime() - d);
return date
}
//For Mumbai time difference is 5.5 hrs so
city_time_diff=5.5; //change according to your city
let time_now = Date.now();
time_now = time_now + (3600000 * city_time_diff); //Add our city time (in msec);
let new_date = new Date(time_now);
console.log("My city time is: ", new_date);
Was facing the same issue, used this one
Console.log(Date.parse("Jun 13, 2018 10:50:39 GMT+1"));
It will return milliseconds to which u can check have +100 timzone intialize British time
Hope it helps!!

How to initialize a JavaScript Date to a particular time zone

I have date time in a particular timezone as a string and I want to convert this to the local time. But, I don't know how to set the timezone in the Date object.
For example, I have Feb 28 2013 7:00 PM ET, then I can
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
As far as I know, I can either set the UTC time or local time. But, how do I set time in another timezone?
I tried to use the add/subtract the offset from UTC but I don't know how to counter daylight savings. Am not sure if I am heading the right direction.
How can I go about converting time from a different timezone to local time in javascript?
Background
JavaScript's Date object tracks time in UTC internally, but typically accepts input and produces output in the local time of the computer it's running on. It has very few facilities for working with time in other time zones.
The internal representation of a Date object is a single number, representing the number of milliseconds that have elapsed since 1970-01-01 00:00:00 UTC, without regard to leap seconds.
There is no time zone or string format stored in the Date object itself.
When various functions of the Date object are used, the computer's local time zone is applied to the internal representation. If the function produces a string, then the computer's locale information may be taken into consideration to determine how to produce that string. The details vary per function, and some are implementation-specific.
The only operations the Date object can do with non-local time zones are:
It can parse a string containing a numeric UTC offset from any time zone. It uses this to adjust the value being parsed, and stores the UTC equivalent. The original local time and offset are not retained in the resulting Date object. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toISOString() //=> "2020-04-12T16:00:00.000Z"
d.valueOf() //=> 1586707200000 (this is what is actually stored in the object)
In environments that have implemented the ECMASCript Internationalization API (aka "Intl"), a Date object can produce a locale-specific string adjusted to a given time zone identifier. This is accomplished via the timeZone option to toLocaleString and its variations. Most implementations will support IANA time zone identifiers, such as 'America/New_York'. For example:
var d = new Date("2020-04-13T00:00:00.000+08:00");
d.toLocaleString('en-US', { timeZone: 'America/New_York' })
//=> "4/12/2020, 12:00:00 PM"
// (midnight in China on Apring 13th is noon in New York on April 12th)
Most modern environments support the full set of IANA time zone identifiers (see the compatibility table here). However, keep in mind that the only identifier required to be supported by Intl is 'UTC', thus you should check carefully if you need to support older browsers or atypical environments (for example, lightweight IoT devices).
Libraries
There are several libraries that can be used to work with time zones. Though they still cannot make the Date object behave any differently, they typically implement the standard IANA timezone database and provide functions for using it in JavaScript. Modern libraries use the time zone data supplied by the Intl API, but older libraries typically have overhead, especially if you are running in a web browser, as the database can get a bit large. Some of these libraries also allow you to selectively reduce the data set, either by which time zones are supported and/or by the range of dates you can work with.
Here are the libraries to consider:
Intl-based Libraries
New development should choose from one of these implementations, which rely on the Intl API for their time zone data:
Luxon (successor of Moment.js)
date-fns-tz (extension for date-fns)
Day.js (when using its Timezone plugin)
Non-Intl Libraries
These libraries are maintained, but carry the burden of packaging their own time zone data, which can be quite large.
js-joda/timezone (extension for js-joda)
moment-timezone* (extension for Moment.js)
date-fns-timezone (extension for older 1.x of date-fns)
BigEasy/TimeZone
tz.js
* While Moment and Moment-Timezone were previously recommended, the Moment team now prefers users chose Luxon for new development.
Discontinued Libraries
These libraries have been officially discontinued and should no longer be used.
WallTime-js
TimeZoneJS
Future Proposals
The TC39 Temporal Proposal aims to provide a new set of standard objects for working with dates and times in the JavaScript language itself. This will include support for a time zone aware object.
Common Errors
There are several approaches that are often tried, which are in error and should usually be avoided.
Re-Parsing
new Date(new Date().toLocaleString('en', {timeZone: 'America/New_York'}))
The above approach correctly uses the Intl API to create a string in a specific time zone, but then it incorrectly passes that string back into the Date constructor. In this case, parsing will be implementation-specific, and may fail entirely. If successful, it is likely that the resulting Date object now represents the wrong instant in time, as the computer's local time zone would be applied during parsing.
Epoch Shifting
var d = new Date();
d.setTime(d.getTime() + someOffset * 60000);
The above approach attempts to manipulate the Date object's time zone by shifting the Unix timestamp by some other time zone offset. However, since the Date object only tracks time in UTC, it actually just makes the Date object represent a different point in time.
The same approach is sometimes used directly on the constructor, and is also invalid.
Epoch Shifting is sometimes used internally in date libraries as a shortcut to avoid writing calendar arithmetic. When doing so, any access to non-UTC properties must be avoided. For example, once shifted, a call to getUTCHours would be acceptable, but a call to getHours would be invalid because it uses the local time zone.
It is called "epoch shifting", because when used correctly, the Unix Epoch (1970-01-01T00:00:00.000Z) is now no longer correlated to a timestamp of 0 but has shifted to a different timestamp by the amount of the offset.
If you're not authoring a date library, you should not be epoch shifting.
For more details about epoch shifting, watch this video clip from Greg Miller at CppCon 2015. The video is about time_t in C++, but the explanation and problems are identical. (For JavaScript folks, every time you hear Greg mention time_t, just think "Date object".)
Trying to make a "UTC Date"
var d = new Date();
var utcDate = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()));
In this example, both d and utcDate are identical. The work to construct utcDate was redundant, because d is already in terms of UTC. Examining the output of toISOString, getTime, or valueOf functions will show identical values for both variables.
A similar approach seen is:
var d = new Date();
var utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds());
This is approach passes UTC values into the Date constructor where local time values are expected. The resulting Date object now represents a completely different point in time. It is essentially the same result as epoch shifting described earlier, and thus should be avoided.
The correct way to get a UTC-based Date object is simply new Date(). If you need a string representation that is in UTC, then use new Date().toISOString().
As Matt Johnson said
If you can limit your usage to modern web browsers, you can now do the
following without any special libraries:
new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
This isn't a comprehensive solution, but it works for many scenarios
that require only output conversion (from UTC or local time to a
specific time zone, but not the other direction).
So although the browser can not read IANA timezones when creating a date, or has any methods to change the timezones on an existing Date object, there seems to be a hack around it:
function changeTimezone(date, ianatz) {
// suppose the date is 12:00 UTC
var invdate = new Date(date.toLocaleString('en-US', {
timeZone: ianatz
}));
// then invdate will be 07:00 in Toronto
// and the diff is 5 hours
var diff = date.getTime() - invdate.getTime();
// so 12:00 in Toronto is 17:00 UTC
return new Date(date.getTime() - diff); // needs to substract
}
// E.g.
var here = new Date();
var there = changeTimezone(here, "America/Toronto");
console.log(`Here: ${here.toString()}\nToronto: ${there.toString()}`);
This should solve your problem, please feel free to offer fixes. This method will account also for daylight saving time for the given date.
dateWithTimeZone = (timeZone, year, month, day, hour, minute, second) => {
let date = new Date(Date.UTC(year, month, day, hour, minute, second));
let utcDate = new Date(date.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(date.toLocaleString('en-US', { timeZone: timeZone }));
let offset = utcDate.getTime() - tzDate.getTime();
date.setTime( date.getTime() + offset );
return date;
};
How to use with timezone and local time:
dateWithTimeZone("America/Los_Angeles",2019,8,8,0,0,0)
You can specify a time zone offset on new Date(), for example:
new Date('Feb 28 2013 19:00:00 EST')
or
new Date('Feb 28 2013 19:00:00 GMT-0500')
Since Date store UTC time ( i.e. getTime returns in UTC ), javascript will them convert the time into UTC, and when you call things like toString javascript will convert the UTC time into browser's local timezone and return the string in local timezone, i.e. If I'm using UTC+8:
> new Date('Feb 28 2013 19:00:00 GMT-0500').toString()
< "Fri Mar 01 2013 08:00:00 GMT+0800 (CST)"
Also you can use normal getHours/Minute/Second method:
> new Date('Feb 28 2013 19:00:00 GMT-0500').getHours()
< 8
( This 8 means after the time is converted into my local time - UTC+8, the hours number is 8. )
I found the most supported way to do this, without worrying about a third party library, was by using getTimezoneOffset to calculate the appropriate timestamp, or update the time then use the normal methods to get the necessary date and time.
var mydate = new Date();
mydate.setFullYear(2013);
mydate.setMonth(02);
mydate.setDate(28);
mydate.setHours(7);
mydate.setMinutes(00);
// ET timezone offset in hours.
var timezone = -5;
// Timezone offset in minutes + the desired offset in minutes, converted to ms.
// This offset should be the same for ALL date calculations, so you should only need to calculate it once.
var offset = (mydate.getTimezoneOffset() + (timezone * 60)) * 60 * 1000;
// Use the timestamp and offset as necessary to calculate min/sec etc, i.e. for countdowns.
var timestamp = mydate.getTime() + offset,
seconds = Math.floor(timestamp / 1000) % 60,
minutes = Math.floor(timestamp / 1000 / 60) % 60,
hours = Math.floor(timestamp / 1000 / 60 / 60);
// Or update the timestamp to reflect the timezone offset.
mydate.setTime(mydate.getTime() + offset);
// Then Output dates and times using the normal methods.
var date = mydate.getDate(),
hour = mydate.getHours();
EDIT
I was previously using UTC methods when performing the date transformations, which was incorrect. With adding the offset to the time, using the local get functions will return the desired results.
For Ionic users, I had hell with this because .toISOString() has to be used with the html template.
This will grab the current date, but of course can be added to previous answers for a selected date.
I got it fixed using this:
date = new Date();
public currentDate: any = new Date(this.date.getTime() - this.date.getTimezoneOffset()*60000).toISOString();
The *60000 is indicating the UTC -6 which is CST so whatever TimeZone is needed, the number and difference can be changed.
I ran into this issue running a GCP Cloud Function. Of course it works on a local machine, but running in the cloud makes the OS default (local) for new Date() irrelevant. In my case, an api call from the cloud required Eastern Standard Time, in ISO format (without the "Z") with offset as "-0500" or "-0400" depending on DST, for example:
2021-12-01T00:00:00.000-0500
Again, this is not a browser formatting issue, so I am forced into this format for the api call to work correctly.
Using #chickens code as a start, this is what worked:
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
var dt = new Date(now_utc);
let utcDate = new Date(dt.toLocaleString('en-US', { timeZone: "UTC" }));
let tzDate = new Date(dt.toLocaleString('en-US', { timeZone: "America/New_York" }));
let offset1 = utcDate.getTime() - tzDate.getTime();
let offset2 = offset1/60000;
let o1 = Math.abs(offset2);
console.log(offset2)
var offsetValue1 = (offset2 < 0 ? "+" : "-") + ("00" + Math.floor(o1 / 60)).slice(-2) + ("00" + (o1 % 60)).slice(-2);
console.log(offsetValue1)
dt.setTime(dt.getTime() - offset1);
console.log(dt.toISOString());
console.log(dt.toISOString().slice(0,-1)+offsetValue1);
I ran into a similar problem with unit tests (specifically in jest when the unit tests run locally to create the snapshots and then the CI server runs in (potentially) a different timezone causing the snapshot comparison to fail). I mocked our Date and some of the supporting methods like so:
describe('...', () => {
let originalDate;
beforeEach(() => {
originalDate = Date;
Date = jest.fn(
(d) => {
let newD;
if (d) {
newD = (new originalDate(d));
} else {
newD = (new originalDate('2017-05-29T10:00:00z'));
}
newD.toLocaleString = () => {
return (new originalDate(newD.valueOf())).toLocaleString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleDateString = () => {
return (new originalDate(newD.valueOf())).toLocaleDateString("en-US", {timeZone: "America/New_York"});
};
newD.toLocaleTimeString = () => {
return (new originalDate(newD.valueOf())).toLocaleTimeString("en-US", {timeZone: "America/New_York"});
};
return newD;
}
);
Date.now = () => { return (Date()); };
});
afterEach(() => {
Date = originalDate;
});
});
I had the same problem but we can use the time zone we want
we use .toLocaleDateString()
eg:
var day=new Date();
const options= {day:'numeric', month:'long', year:"numeric", timeZone:"Asia/Kolkata"};
const today=day.toLocaleDateString("en-IN", options);
console.log(today);
Try using ctoc from npm.
https://www.npmjs.com/package/ctoc_timezone
It has got simple functionality to change timezones (most timezones around 400) and all custom formats u want it to display.
Building on the answers above, I am using this native one liner to convert the long timezone string to the three letter string:
var longTz = 'America/Los_Angeles';
var shortTz = new Date().
toLocaleString("en", {timeZoneName: "short", timeZone: longTz}).
split(' ').
pop();
This will give PDT or PST depending on the date provided. In my particular use case, developing on Salesforce (Aura/Lightning), we are able to get the user timezone in the long format from the backend.
Thanks to #commonpike answer, I wrote a function which takes an ISO String date such as 2020-10-10T08:00:00.000 as input and send an object which contains 2 main properties.
The first one is fromUtc is a Date corresponding to the timeZone entered as parameter.
The second one is toUtc which lets you to format a Date stemming from fromUtc.
const timeZoneTransformer = (stringDate, timeZone = "Europe/Paris") => {
const now = new Date();
const serverDate = new Date(stringDate);
const utcDate = new Date(
Date.UTC(
serverDate.getFullYear(),
serverDate.getMonth(),
serverDate.getDate(),
serverDate.getHours(),
serverDate.getMinutes(),
serverDate.getSeconds()
)
);
const invdate = new Date(
serverDate.toLocaleString("en-US", {
timeZone,
})
);
const diff = now.getTime() - invdate.getTime();
const adjustedDate = new Date(now.getTime() - diff);
return {
toUtc: utcDate,
fromUtc: adjustedDate,
};
};
const fromUtc = timeZoneTransformer("2020-10-10T08:00:00.000").fromUtc;
console.log(fromUtc);
const toUtc = timeZoneTransformer(fromUtc).toUtc;
console.log(toUtc);
Try: date-from-timezone, it resolves expected date with help of natively available Intl.DateTimeFormat.
I used that method in one of my projects for few years already, but it's now I decided to publish it as small OS project :)
Try something like this,
public static getTimezoneOffset(timeZone: string, date = new Date()): number {
const localDate = date.toLocaleString('fr', { timeZone, timeZoneName: 'long' });
const tz = localDate.split(' ');
const TZ = localDate.replace(tz[0], '').replace(tz[1], '').replace(' ', '');
const dateString = date.toString();
const offset = (Date.parse(`${dateString} UTC`) - Date.parse(`${dateString}${TZ}`)) / (3600 * 1000);
return offset;
}
I'm not sure why all these answers are so complicated. Just use YYYY-MM-DD ZZZ when creating a date-only date in the local / desired time zone.
Create a local date:
var myDate = new Date('2022-11-29 CST')
The date will be stored in storage as UTC, great.
Get the date out of storage and display it as local:
myDate.toLocaleDateString()
11/29/2022
I know its 3 years too late, but maybe it can help someone else because I haven't found anything like that except for the moment-timezone library, which is not exactly the same as what he's asking for here.
I've done something similar for german timezone,
this is a little complex because of daylight saving time and leap years where you have 366 days.
it might need a little work with the "isDaylightSavingTimeInGermany" function while different timezones change on different times the daylight saving time.
anyway, check out this page:
https://github.com/zerkotin/german-timezone-converter/wiki
the main methods are:
convertLocalDateToGermanTimezone
convertGermanDateToLocalTimezone
I've put an effort into documenting it, so it won't be so confusing.
There are several working answers here, but somehow a lot of them seemed to get you to the string, but not back to a date object you started with, so here's my simple non-function take on how to change timezone on JS date:
var TZ='Australia/Brisbane'; //Target timezone from server
var date = new Date(); //Init this to a time if you don't want current time
date=new Date(Date.parse(date.toLocaleString("en-US", {timeZone: TZ})));
//Just a clarification on what happens
// 1) First new Date() gives you a Date object at current time in the clients browser local timezone
// 2) .toLocaleString takes that time, and returns a string if time in the target timezone
// 3) Date.parse converts that new string to a Unix epoch number
// 4) new Date() converts the Unix epoch into a Date object in the new TimeZone.
// Now I can use my usual getHours and other Date functions as required.
Hope that helps others (if you get to this bottom answer!)
Simple with Node.JS support
Pass in the amount of hours your timezone is offset from UTC
function initDateInTimezone(offsetHours) {
const timezoneOffsetInMS = offsetHours * 60 * 60000;
let d = new Date().getTimezoneOffset() * 60000 + timezoneOffsetInMS;
const date = new Date(new Date().getTime() - d);
return date
}
//For Mumbai time difference is 5.5 hrs so
city_time_diff=5.5; //change according to your city
let time_now = Date.now();
time_now = time_now + (3600000 * city_time_diff); //Add our city time (in msec);
let new_date = new Date(time_now);
console.log("My city time is: ", new_date);
Was facing the same issue, used this one
Console.log(Date.parse("Jun 13, 2018 10:50:39 GMT+1"));
It will return milliseconds to which u can check have +100 timzone intialize British time
Hope it helps!!

Javascript countdown using absolute timezone?

I have a javascript countdown timer that works by taking a specified date and time, and comparing it to the current date and time. The issue is, the current time is relative to the users timezone, so the time remaining is different between users.
How can I have the timer countdown till a time in a specific timezone, in my case GMT -5 hours?
I understand i can use the below code to get the users timezone, but I am lost as how to use this.
myDateObj.getTimezoneOffset( ) / 60
You can use Date.UTC(year,month,day,hours,minutes,seconds,msec)
It operates just like the Date constructor, but returns the timestamp of the arguments at Greenwich time (offset=0) instead of local time.
var localtime=new Date(Date.UTC(year,month,day,hours,minutes,seconds,msec))
returns the local time for the UTC time specified.
Everyone (whose clock is set correctly) will end the countdown together.
A quick search reveals: convert-the-local-time-to-another-time-zone-with-this-javascript
Following the article verbatim gets you this example:
var d = new Date();
var localTime = d.getTime();
var localOffset = d.getTimezoneOffset() * 60000;
var utc = localTime + localOffset;
// obtain and add destination's UTC time offset
// for example, Bombay
// which is UTC + 5.5 hours
var offset = 5.5;
var bombay = utc + (3600000*offset);
var nd = new Date(bombay);
alert("Bombay time is " + nd.toLocaleString() + "<br>");
jsFiddle: http://jsfiddle.net/GEpaH/
Just update with your desired offset and you should be all set.
Just create a Date with an RFC 2822-timestamp with timezone. That time will then be converted to the users current location (based on OS settings). Even with corrections for daylight savings time!
I'm in Norway, which currently is in daylight savings time, so it's GMT+2. Here is what happens when I create a Date object using GMT-0500:
var myDateObj = new Date("Fri Apr 17 2015 12:00:00 GMT-0500 (CDT)");
myDateObj.toString();
Fri Apr 17 2015 19:00:00 GMT+0200 (CEST)
How to get the correct date string for your location? If it's the timezone you're currently in; just do myDateObj.toString() in your browsers dev-tools console. For a different timezone; change the timezone in your operating system first. (Or read the RFC)
new Date().toString();
Fri Apr 17 2015 12:36:57 GMT+0200 (CEST)
You don't really say exactly what your are trying to accomplish. The javascript date object retrieves the local time and the "timezone offset" (relative to GMT (UTC)). These are of course "set" by the user so even if in the same time zone, two users are very unlikely to have the same "time".
If you are trying to time between different users you need to be referencing some centralized time authority.
I would use an AJAX type call (XMLHttpRequest) to a page own my own server that returns my server's time. That way each user is referencing the same time.
Google XMLHttpRequest to find examples of the JS code you need (and oftentimes the corresponding server-side code for a simple service such as this).
PS: I would also install some simple client software to keep the time on my server accurate by synching with an atomic clock every 10 minutes.
You can't get an accurate date with JavaScript as it is client-side and it is based on the user's operating system clock. You can use jCounter to display countdowns based on server-side timezones.
But hey, if you really want to do it yourself, download jCounter and you'll find a dateandtime.php file as well which retrieves the current date server-side, as timestamp (it will have to be placed on a server btw, not on your desktop :P)
Check how that script uses that file and retrieves the real current date to operate against it and calculate accurate countdowns.
Cheers
To revise the approach Brandon has taken to calculate a UTC-shifted time, we can slim the code down into a two-line extension of the Date object:
/* getOffsetDate - Returns a Date shifted by a certain offset
* #param offset the UTC offset to shift, in hours
* #return new date object shifted by UTC offset
*/
Date.prototype.getOffsetDate = function( offset ) {
utc = this.getTime() + (this.getTimezoneOffset() * 60000);
return new Date(utc + (3600000*offset));
}
You can then calculate the UTC-5 shifted date as follows:
myDate = new Date().getOffsetDate(-5);
It should be noted that extending native prototypes in this manner is generally considered a bad practice since it muddles core objects that other libraries depend upon. To justify it, you'd have to argue this functionality should be a native part of the Date object.

Categories