This question already has answers here:
Why does Date.parse give incorrect results?
(11 answers)
Closed 2 years ago.
I have a date: yyyy-mm-dd that I am formatting using the International DateTimeFormat like this:
const formatter = new Intl.DateTimeFormat("en-US", { month: '2-digit', day: '2-digit', year: 'numeric', timeZone:'America/Denver'});
// GiVES SAME RESULTS AS ABOVE
//const formatter = new Intl.DateTimeFormat("en-US", { month: '2-digit', day: '2-digit', year: 'numeric'});
//const formatter = new Intl.DateTimeFormat("default" , { month: '2-digit', day: '2-digit', year: 'numeric'});
let date = "2020-03-19"
return formatter.format(Date.parse(date));
//returns 03/18/2020 which is one day behind
I've tried this with and without the timeZone attribute. How can I fix this?
The ECMAScript Date Time String Format defines formats for both date-time forms as well as date-only forms. These are used by the Date.parse function and the Date constructor when a string is passed. Behavior for those functions is defined in the docs for the Date.parse function, which contain the following statement:
... When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.
Thus, when you call Date.parse('2020-03-19') the defined behavior is to treat that as UTC, not as local time. (This deviates from ISO 8601.)
To change this behavior, append a time string or a time+offset string.
For example, if you want to parse the time in the local computer's time zone:
Date.parse('2020-03-19T00:00:00.000')
Or, if you want to parse in a particular time zone and know the correct offset for the given timestamp in that time zone:
Date.parse('2020-03-19T00:00:00.000-05:00')
Often one doesn't know the offset, but does know the IANA time zone identifiers (such as 'America/Chicago'). Unfortunately, ECMAScript doesn't currently have the capability to parse in a named time zone yet. That capability will be possible if/when the TC39 Temporal proposal is adopted. Until then, you could use a library such as Luxon to perform such an action. For example:
luxon.DateTime.fromISO('2020-03-19', { zone: 'America/Chicago' }).toString()
//=> "2020-03-19T00:00:00.000-05:00"
Date.parse("2020-03-19") indicates 2020-03-19 00:00:00 GMT, so it will be 2020-03-18 for America/Denver, which will be 2020-03-18 17:00:00 America/Denver
const formatter1 = new Intl.DateTimeFormat("en-US", { month: '2-digit', day: '2-digit', year: 'numeric', timeZone:'America/Denver'});
const formatter2 = new Intl.DateTimeFormat("en-US", { month: '2-digit', day: '2-digit', year: 'numeric'});
let date = "2020-03-19"
console.log(formatter1.format(Date.parse(date)));
console.log(formatter2.format(Date.parse(date)));
You have added time zone, because of that it convert date into that time zone and because of the zone it can be 1 day behind or next day.
Related
I am using Javascript code such as that shown below, and recently found that while Date.prototype.toLocaleTimeString() on one machine appends " GMT" or " BST" (depending on the time of year); on another machine, nothing is appended.
var m = new Date();
var time = m.toLocaleTimeString();
I use the returned string to create a log file, and would like the file names to have a canonical structure. I don't mind which of the two string formats is returned, as long as it is the same on both machines.
By the way, I also tried providing first and second arguments, such as m.toLocaleTimeString('en-gb', { hour: '2-digit', minute: '2-digit', second: '2-digit' }), or m.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }), but then the seconds are no longer included in the returned string.
You could create a custom format function for your logs, using the Date.getHours(), getMinutes() etc.
This should be consistent across platforms and would allow any customization to be added easily.
function formatTimestamp(date) {
const hms = [date.getHours(), date.getMinutes(), date.getSeconds()];
return hms.map(s => (s + '').padStart(2, '0')).join(':');
}
console.log('Timestamp:', formatTimestamp(new Date()));
The behavior you are seeing with the toLocaleTimeString() method is likely due to differences in the default time zone settings on the two machines. The method returns a string that represents the time in the current time zone, which can be different depending on the machine's settings.
You can use toUTCString() method to get a string representation of the date in UTC format, this will always return the same format, regardless of the machine's time zone settings.
var m = new Date();
var time = m.toUTCString();
Another approach, you can use moment.js library, this library will handle timezone and other time related issues, and it's very useful when you are working with dates and time, it will give you a consistent format across different environments.
var moment = require('moment');
var time = moment().format('HH:mm:ss');
The moment().format('HH:mm:ss') will give you the time in the format of HH:mm:ss and you can use this as your log file name.
Additionally, you can also set your machine's time zone to a specific value using the Intl.DateTimeFormat() method, this will help you to get the same format across different machines.
var m = new Date();
var options = {timeZone: 'UTC', hour: '2-digit', minute: '2-digit', second: '2-digit'};
var time = new Intl.DateTimeFormat('en-GB', options).format(m);
This will give you the time formatted to 'en-GB' time zone and with the hour, minute and second digits.
I'm trying to convert the string 2022-02-01T13:36:57+00:00 to a Date object javascript that returns me Tue Feb 01 2022 13:36:57 without considering the timezone.
But everytime that I try to convert the date it returns:
Tue Feb 01 2022 10:36:57 GMT-0300 (Brasilia Standard Time)
I already tried with moment:
let now = moment("2022-02-01T13:36:57+00:00").toDate();
with Date:
let now = new Date("2022-02-01T13:36:57+00:00");
with UTC too: new Date(Date.UTC(2022, 02, 01, 10, 36, 57))
But all of them returns me the local date (Brasilia Standard Time)
So, the question is:
How can I convert this string 2022-02-01T13:36:57+00:00 to a Date object that keeps the same day, hour, etc ?
The timestamp "2022-02-01T13:36:57+00:00" represents a unique moment in time. If parsed to a Date object, it will create a Date instance with a time value of 1643722617000, which is the offset in milliseconds from the ECMAScript epoch of 1 Jan 1970.
The time value produced from the timestamp is unaffected by local settings as:
It conforms to one of the formats supported by ECMA-262 and therefore parsing is specified by the standard
Contains a fixed offset
The default toString method produces a timestamp for the equivalent date and time in the timezone of the host system, typically called the local date and time. It will produce a different date and time for each host with a different offset, but they will all represent exactly the same moment in time.
E.g.
let timestamp = '2022-02-01T13:36:57+00:00';
let date = new Date(timestamp);
['UTC','America/Sao_Paulo','Asia/Kolkata'].forEach(
loc => console.log(`${date.toLocaleString('default',{timeZone:loc})} - ${loc}`)
)
If you want the timestamp to be parsed as local (and that should only be done if you know what you are doing and have a very good reason to do so) then remove the offset and parse the remainder:
let timestamp = '2022-02-01T13:36:57+00:00';
let date = new Date(timestamp.substring(0,19));
console.log(date.toString());
Note that the resulting Date represents a different moment in time for each host with a different offset and each such date instance will have a different time value.
You can instantiate your own Intl.DateTimeFormat formatter, or call Date.prototype.toLocaleString().
const
dateString = '2022-02-01T13:36:57+00:00',
date = new Date(dateString),
dateFormatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'UTC',
weekday: 'short',
year: 'numeric',
month: 'short',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName: 'long',
hour12: false
});
console.log(`Local date : ${date}`);
console.log(` UTC date : ${dateFormatter.format(date).replace(/,/g, '')}`);
How can i convert this 2021-01-10 12:47:29 UTC to January 10, 2021?
I'm using this below using moment.js but this works browsers but not in Safari
{moment(video?.createdAt).format('MMMM D, YYYY')}
Moment.js is deprecated. Here's an alternative using native JS features.
First we need to convert the date string into a Date object. Calling new Date(video?.createdAt) is not reliable as mentioned on the Date() constructor page on MDN:
Parsing of date strings with the Date constructor
(and Date.parse(), which works the same way)
is strongly discouraged due to browser differences and inconsistencies.
See Date Time String Format on MDN for reference of the correct format. For example:
// This expects inputs in the form of
// `2021-01-10 12:47:29 UTC`
function parseDate(dateString) {
const [date, time] = dateString.split(' ')
return new Date(`${date}T${time}.000Z`) // Z = UTC
}
Then we can use Date.prototype.toLocaleString() to format the Date object:
// This expects inputs in the form of
// `2021-01-10 12:47:29 UTC`
function parseDate(dateString) {
const [date, time] = dateString.split(' ')
return new Date(`${date}T${time}.000Z`) // Z = UTC
}
function format(dateString) {
if (!dateString) return 'some fallback value'
const date = parseDate(dateString)
return date.toLocaleString('en', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
})
}
console.log(format('2021-01-10 12:47:29 UTC'))
//=> January 10, 2021, 2:47 PM
console.log(format(undefined))
//=> some fallback value
See Intl.DateTimeFormat() for all possible options. For example, these options produce slightly different results:
return date.toLocaleString('en', {
dateStyle: 'long',
timeStyle: 'short',
})
format('2021-01-10 12:47:29 UTC')
//=> January 10, 2021 at 2:47 PM
If the date strings can be in various formats, you probably need more robust date parsing. Or if you need exotic formattings, toLocaleString() might not meet your needs. In those cases, it might be useful to use one of the recommended Moment.js alternatives.
The new Intl DateTimeFormat API is gaining more support natively in many browsers, so it is a more future proof solution. As suggested in the doc, you can use polyfills for browsers which lack full support of this feature. Unfortunately, Safari is one of the browser which is yet to catch up.
A short snippet to achieve what you are looking for would be
new Intl.DateTimeFormat('en-US', { dateStyle: 'long'}).format(new Date("2021-01-10 12:47:29Z")) // outputs January 10, 2021
Keep in mind that date time string without Z at the end would be parsed as local time. Z means the date time supplied is UTC.
If you're searching for moment.js alternative, I would suggest date-fns. Here is a blog post that compares the 2 of them.
Here is the format documentation for date-fns.
So to answer your question using date-fns:
format(new Date(video?.createdAt), 'MMMM D, YYYY')
I have a date and need to convert it into this format
02/27/2020 3:00PM (MST)
What is the fastest way to do that in javscript like a one liner?
I tried
var options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute:'numeric', timeZoneName: 'short' };
this.date = new Date().toLocaleDateString("en-US", options);
This also does not work
new Date().toLocaleDateString(Intl.DateTimeFormat().resolvedOptions().timeZone, options);
as I am getting asia/caluctta invalid language tag
While this works for UnitedStates this does not work for users in russia, india, europe, china.
It will show the date as
02/28/2020 +500 GMT
I need it to show as
02/28/2020 (IST) for India
or
02/28/2020 (JST) for Japan Standard time
I can recommend you to try Moment.js. It's a javascript library made especially for easier manipulation with time. Just download the .js and add it to your index.html before your script.
I have an initial value for a timestamp (created in User-1's timezone) I'm retrieving from firebase's firestore. the format this is in, is seconds in UTC from the Unix Epoch.
My goal is to take the initial timestamp value, and convert it to the timezone of the current user. if I use
moment.unix(initial_In_Seconds).format("H:mma") I get the correct initial time. Using .unix() is the only way I've been able to get the correct initial time. Now I need to convert it to a specific timezone. lets say "America/Denver" (the initial timezone is GMT -05:00)
I haven't been successful using moment.tz() in any of my amalgamations thus far.
I've tried:
moment.tz(moment.unix(initial_In_Seconds).format("H:mma"), "America/Denver")
let unix = moment.unix(initial_In_Seconds).format("H:mma");
let parsed = moment.tz(unix, "America/Denver");
How can this be parsed? Moment.js confuses me
If your timezone offset is specified using IANA representative locations, such as 'America/Denver', then you can likely use toLocaleString provided the locations aren't too obscure (i.e. aren't unsupported by ECMAScript implementations likely to run your code), e.g.
function timeValueWithTimezone(unixOffset, loc) {
let d = new Date(unixOffset * 1000);
return d.toLocaleString(void 0, {
hour12: true,
hour: 'numeric',
minute: '2-digit',
timeZone: loc
});
}
let timeValue = 1582090120;
let loc = 'America/Denver';
console.log('At your local time: ' +
new Date(timeValue * 1000).toLocaleString(void 0, {
hour12: true,
hour: 'numeric',
minute: '2-digit'
}));
console.log('Denver local time is: ' + timeValueWithTimezone(timeValue, loc));
further playing has yielded better results:
moment
.tz(moment.unix(props.navigation.state.params.time.start.seconds),'America/Denver')
.format('H:mma')
unfortunately for hours that are PM, it gives military time...and im interested in 12hr format...
EDIT: changes -> .format('h:mma') yields 12hr format