In Javascript, given a string representing a date like this one:
var dateFromPrague = "2011-10-10T14:48:00"
And knowing above date is a date from a specific localization, like Europe/Prague, how could I get this date translated to the local hour? I know I can create a Date object indicating timezone offset like this:
var dateFromPrague = new Date("2011-10-10T14:48:00.000+02:00");
Then I could get local date from above date like this:
var dateFromPragueTolocalDate = dateFromPrague.toString();
But Prague offset is not always +02:00 as it depends on DST being applied or not (summer or winter hours). So How could I indicate the right timezone, something like 'Europe/Prague', or achieve this translation some way (returning offset from server is not possible)?
There isn't currently anything built into JavaScript itself (or the browser platform) that lets you do this, no, you're in the land of libraries. In a couple of years you'll probably be able to use Temporal, but it's still at an early stage in the proposals process. There's a polyfill linked from the proposal, but the part you'd want to use would probably be the provisionally-named LocalDateTime (not its final name) which is still a work in progress.
One library that you can do this with is Moment Timezone. That looks like this:
var a = moment.tz(dateFromPrague, "Europe/Prague");
Live Example:
var dateFromPrague = "2011-10-10T14:48:00";
var a = moment.tz(dateFromPrague, "Europe/Prague");
console.log(a.toDate());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data.min.js"></script>
You should get the dates in UTC from server and then you can use date.toLocaleDateString() to convert to local date. This is the typical approach.
Related
This will be my first time working with time zones, I hear this is a major pain point for a lot of developers so I'm asking this question as a sanity check to make sure I'm not missing anything.
My use case is rather "simple", I want to have a date time picker where the user can choose their date and time in their local timezone (in other words what they see in the picker matches what their computer's date and time is set to).
Then I want to take this chosen date and time, convert it to UTC and send it to the server to be saved.
When the user goes to certain pages I take the UTC date/time coming back from the server and convert it to the user's local date/time and display it to them in a user friendly way.
Do I need a library like moment timezone for this or will the browser's native date methods like Intl.DateTimeFormat, new Date().getTimezoneOffset(), etc be enough? (I only need to support the latest modern browsers so I'm asking this from a "does it do what I need" ​point of view not a browser support POV).
It seems all I need are 2 things:
A way to get the user's timezone offset from UTC (so I can convert their local time to UTC to send to the server and also to convert UTC back to their local time to display it to them on certain pages)
A way get their timezone abbreviation (EST, PDT, CDT, etc) to show in the UI
Do I need a library for these? And if not why do people use such large libraries for working with timezones anyway?
You don't need a time zone library for the functionality you mentioned.
// Get a Date object from your date picker, or construct one
const d1 = new Date("2020-08-02T10:00");
// Convert it to a UTC-based ISO 8601 string for your back-end
const utcString = d1.toISOString();
// Later, you can create a new Date object from the UTC string
const d2 = new Date(utcString);
// And you can display it in local time
const s1 = d2.toString();
// Or you can be a bit more precise with output formatting if you like
const s2 = d2.toLocaleString(undefined, {timeZoneName: 'short'});
console.log("UTC: ", utcString);
console.log("Local Time (default string): ", s1);
console.log("Local Time (intl-based string): ", s2);
Keep in mind that not all time zones will have an abbreviation, so those ones will give output like "GMT+3".
I am in Hawaii. From Angular, I want to send Pacific Standard Time (PST) to C# Net Core API. It will save it in database and save in Pacific Standard Time. (I didn't create the architecture, just noting).
The whole Angular Application date/times are written in reference of PST.
Example goal is to Schedule Date at 4:30PM PST
We learned a bug today, if we send a date "2021-03-17T16:30:00" , our application creates new Date("2021-03-17T16:30:00") in Hawaii Timezone misinterprets. Then C# probably does the right thing, and converts any time to Pacific Local time (TimeZoneInfo.ConvertTime(dateTime, TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles")). Thus we incorrectly convert to 7:30PM.
Our API Request Data type is in Date. Would this solution work? however, I feel last 4th line will not account for Daylight savings, or can create issue.
const inputDate = "2021-03-17T16:30:00";
const pstMoment = moment.tz(inputDate, 'America/Los_Angeles');
const clientTimeZoneName = Intl.DateTimeFormat().resolvedOptions().timeZone;
const clientMoment = pstMoment.clone().tz(clientTimeZoneName);
console.log(new Date(clientMoment.format())); // this will send to API
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.33/moment-timezone-with-data-10-year-range.js"></script>
Note: Code resolution should not only work in Hawaii, but other global countries which may Not have Daylight Savings Time. Our schedule datepicker utilizes a string storage type (inputDate).
Typescript class
export interface ScheduleDto {
scheduleDate?: Date;
scheduleDate: "2021-03-18T02:30:00.000Z"
C# class
public class ScheduleDto
{
public DateTime? ScheduleDate { get; set; }
....
return TimeZoneInfo.ConvertTime(ScheduleDate , TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"));
If I understand correctly, the problem is that your current approach on the client-side is just creating a Date object like new Date("2021-03-17T16:30:00"), which is going to use the local time zone to determine the point-in time you're talking about. You want it to always be interpreted as Pacific time, but you don't know which offset to use because of DST.
So then, the ultimate answer to your question is - YES, the code you wrote using Moment-timezone, would indeed apply the correct offset. However, it's a bit verbose. You don't actually need to do anything with regard to detecting the current local time zone. You can instead just build the Date object with:
moment.tz('2021-03-17T16:30:00', 'America/Los_Angeles').toDate()
Given Moment's project status, it would be preferred to use Luxon instead (unless you have already extensively used Moment in your project). In Luxon, that would be:
luxon.DateTime.fromISO('2021-03-17T16:30:00', {zone: 'America/Los_Angeles'}).toJSDate()
Or you could use the zonedTimeToUtc function from date-fns-tz.
The point is, since you're constructing a Date object, you're always sending some string representation of it over the wire. You appear to be serializing those Date objects with .toISOString(), which will send the UTC equivalent "2021-03-18T02:30:00.000Z". Getting that UTC point in time correct is what matters most.
In your .NET code, if you are receiving that value into a DateTime object, then its Kind property will be set to Utc because of the Z at the end of the string. TimeZoneInfo.ConvertTime will use the Kind property to determine the source time zone for the conversion, and you've supplied the destination time zone as Pacific time.
A much simpler approach would be to not use a Date object in your client-side code, but rather you would send the intended date and time over the wire instead, without the offset "2021-03-17T16:30:00". In your .NET code, the DateTime.Kind would be Unspecified. Then you wouldn't call TimeZoneInfo.ConvertTime at all, because you already have the value in the desired time zone.
Alternatives:
For the TypeScript data type, You could use a string.
In the future, when Temporal is finished and fully integrated into ECMAScript, you could use a PlainDateTime.
I know I can get the local timezone offset via new Date().getTimeZoneOffset(). But where did Javascript get that information? Is there a way I can set it, so that all future Date objects have the offset I want? I tried searching the DOM in Firebug, but couldn't find anything.
What I am trying to accomplish is converting epoch times to readable format, but it needs to be in US/Central, no matter what the browser's OS setting. Because I am using US/Central, it's not a fixed difference from GMT. So instead of a bunch of super nasty conversion steps, why can't I just tell Javascript that I'm actually in US/Central?
Currently, Moment-Timezone enables us to set the "browser's" default timezone by using moment.tz.setDefault().
You'll have to use moment() instead of Date(), but this is still a nice upgrade over the weird JS Date object.
I know I can get the local timezone offset via new Date().getTimeZoneOffset(). But where did Javascript get that information?
An implementation of ECMAScript is expected to determine the local time zone adjustment.
Is there a way I can set it, so that all future Date objects have the offset I want?
No.
So instead of a bunch of super nasty conversion steps, why can't I just tell Javascript that I'm actually in US/Central?
Have you considered using a library?
I realize this is an old post, but momentJS is a powerful javascript library to manipulate date/time objects
Output format
If you are concerned about the output format, you always need to format you Date object prior to outputting it if you need it in a local timezone (e.g. using Intl) or you a library like dayjs or moment.
Create a new Date object from a date with a non-UTC timezone
You can set an offset in pure JS: new Date('2022-10-29T12:50:00.000+02:00') will contain 2022-10-29T10:50:00.000Z. You just have to always specify the timezone offset in /^[+-][0-2]\d:[0-5]\d$/ format.
console.log(new Date('2022-10-29T12:50:00.000+02:00').toISOString())
// Output
// 2022-10-29T10:50:00.000Z
Get timezone offset string from timezone offset number
Now, if you want to get an offset in that format from (new Date()).getTimezoneOffset() (e.g. -120), you need to
const tzOffsetNumber = (new Date()).getTimezoneOffset()
const tzOffsetString = `${tzOffsetNumber > 0 ? '+' : '-'}${Math.floor(Math.abs(tzOffsetNumber) / 60).toString().padStart(2, '0')}:${(Math.abs(tzOffsetNumber) % 60).toString().padStart(2, '0')}`
Get timezone offset string from IANA timezone
// Note: We need to specify a date in order to also consider DST settings.
const date = new Date()
const ianaTimezone = 'Europe/Bratislava'
const tzOffsetString = new Intl.DateTimeFormat('en', {timeZone: ianaTimezone, timeZoneName: 'longOffset'}).format(date).match(/[\d+:-]+$/)?.[0]
I have tried to search for the answer already, and although I find answers that are very similar, I don't think they are exactly what I am looking for. Please forgive me if this is already answered elsewhere.
I am trying to parse an ISO date in javascript so that I can compare it to the client system date and display information depending on if the ISO date is before or after the client system date.
This was fine until I needed to support IE8 and now I am stuck.
I have created a function because I have three different dates that I need to do this to.
for example, my ISO date is: 2015-12-22T11:59 in UTC time.
but once my date is parsed, the full date is 11:59 in local time, no matter which time zone i test, it's always 11.59 in THAT time zone.
I know that the function I have created currently doesn't do anything with timezone, this is where I am stuck. I don't know what to add to get my end date to change as a reflection of the timezone of the clients machine.
any help or advice would be greatly appreciated.
I am not able to use something like moments.js because I have an upload restriction.
Jquery is available though. or plain javascript.
<script>
function setSaleContent() {
//creating a new date object that takes the clients current system time. so we can compare it to the dates stored in our array
var currentDate = new Date();
console.log(currentDate + " this is the clients date ");
//These variables actually come from an external array object, but I'm putting them in here like this for this example.
var destinations = {
freedate: "2015-12-16T11:59",
courierdate: "2015-12-22T11:59",
nextdaydate: "2015-12-23T11:59",
}
//fetch all the ISO dates from the array.
var freeDateISO = destinations["freedate"];
var courierDateISO = destinations["courierdate"];
var nextdayDateISO = destinations["nextdaydate"];
//I am creating this reusable function to split up my ISO date for the sake of IE8.. and create it into a date format that can be compared against another date. I know that this isn't doing anything with my timezone and that is where my problem lies.
function parseDate(str) {
var parts = /^(\d{4}).(\d{2}).(\d{2}).(\d{2}):(\d{2})/.exec(str);
if (parts) {
return new Date(parts[1], parts[2] - 1, parts[3], parts[4], parts[5]);
}
return new Date();
}
//I would like this date to change to reflect the time zone of the clients system time.
//currently returns the date at 11.59 regardless of timezone.
//If i was in GMT i would want it to say 11.59
//If i was in CT time I would like this to say 05.59
//If i was in Perth I would like this to say 19:59
var freeDate = parseDate(freeDateISO);
console.log(freeDate + " this is the converted date for IE")
}
window.onload = setSaleContent;
The simple solution is to append Z to the ISO date to indicate it is in UTC time, such as 2015-12-22T11:59Z.
When JavaScript parses that date as a string, it will then automatically convert the UTC date to the local time zone.
While this is simple enough with a parsing call in the form new Date(str);, it will not play nice with your parse call with numerical arguments targeting IE8 and other old browsers.
A polyfill for parsing ISO dates with timezone exists: Javascript JSON Date parse in IE7/IE8 returns NaN
This can replace your custom parseDate function after some modification to take an input string.
Alternatively, implement your own custom date manipulater to account for the local timezone using the .getTimezoneOffset() method on the newly created date, which gives the time zone offset in minutes, but you will have to come up with a method of utilising the offset such as adjusting hours and minutes, due to the limited methods of the JavaScript date object.
On ASP.net MVC application where I save the date on datetime field in SQL sever db.It saves like this 2015-04-22 18:43:18.967.So now I need to show it as MST (Mountain Standard Time) on client side.So how can I do that ? I can use Moment.js or any other JavaScript library for that.Thanks in advance.
If you send the timestamp to the client and you are using momentjs, then it's pretty simple
var day = moment(TS_IN_MILLISECONDS).tz('America/Denver')
With the string you provided, you can do this:
var UTCTime = moment.utc('2015-04-22 18:43:18.967').toDate();
var MSTTime = moment(UTCTime).tz('America/Denver').format('YYYY-MM-DD HH:mm:ss');
So this will depend on what local time your server is running in (or if it's just pulling UTC it'll be a bit easier). But you can yank the timezone offset like this: dateTime.getTimezoneOffset(), modify it it to reflect the offset difference between your server's timezone and MST. And then modify your original datetime to reflect the new offset.
This may be a good post for reference.
Also refer to here:
dateTime.setTime( dateTime.getTime() + dateTime.getTimezoneOffset()*[math to adjust your timezone] );