UTC Date Time to Full Date in ES6 - javascript

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')

Related

How to add specific characters in between values of a JavaScript date?

I am trying to format a date in JavaScript to fit a specific format.
My desired format is 29-Jan-2021
With the below code I have managed to generate "29 Jan 2021":
var newDate = new Date('2021-01-29T12:18:48.6588096Z')
const options = {
year: 'numeric',
month: 'short',
day: 'numeric',
};
console.log(newDate.toLocaleString('en-UK', options))
Can someone please show me how I can add - between the day, month, & year in the date above?
Well you if you have already able to find the string close to your answer you can achieve your solution with either of the two methods.
Either you can use replaceAll() or replace(). Both will be able to solve the issue.
let dateFormat = "29 Jan 2021"
console.log(dateFormat.replaceAll(" ","-")) // 29-Jan-2021
console.log(dateFormat.replace(/ /g,"-")) // 29-Jan-2021
Well I would suggest you to use replace() over replaceAll as some browsers do not support replaceAll(). Do check replaceAll support.

Odd timezone offset when converting

I am trying to use UTC wherever possible. Now I found the following strange behaviour and I really don't understand what ist happening. It would be great, if someone could give advice.
Note: I write my code in the Google Apps Script Editor.
I use the following code to create a date and get the output in my local timezone:
var testDate = Date.UTC(2022,0,1,0,0,0,0);
Logger.log(Utilities.formatDate(new Date(testDate), 'Europe/Berlin', 'dd.MM.yyyy hh:mm'));
The result is 01.01.2022 01:00, as expected, because 'Europe/Berlin' is 1 hour behind UTC. So if I wanted the output to be 01.01.2022 00:00 I would try the following:
var testDate = Date.UTC(2021,11,31,23,0,0,0);
Logger.log(Utilities.formatDate(new Date(testDate), 'Europe/Berlin', 'dd.MM.yyyy hh:mm'));
But the result I get is: 01.01.2022 12:00
Can anybody hint me to why my expectation is wrong?
(I hope my English is okay.)
I don't think we can directly answer the question, because it looks like the issue is that Utilities.formatDate uses 12:00 for midnight (which is one of two valid ways of writing midnight in many systems, especially when using a 12-hour clock, though usually you follow it with something indicating it's 12:00 a.m., not 12:00 p.m.). For instance, here's an example of another formatter doing that because I'm explicitly telling it to use 12-hour time:
const testDate = Date.UTC(2022,0,1,0,0,0,0);
const dateTimeFormat = new Intl.DateTimeFormat("en", {
hour12: true,
timeZone: "UTC",
timeStyle: "short",
}).format;
console.log(dateTimeFormat(testDate));
So you'd have to look at Utilities.formatDate to see if it has an option for 24-hour time or at least using 00:00 for midnight, like some other formatters do.
But more fundamentally, if you're trying to format in UTC, I wouldn't play offset games to do it, not least because Berlin isn't always one hour offset from UTC, sometimes it's two hours offset (daylight saving time).¹ Instead, I'd have a formatter that uses the UTC accessors on Date (getUTCHours, getUTCMonth, etc.) to build the string rather than using the local time version. Either some library, or something that uses Intl.DateTimeFormat. For example:
const testDate = Date.UTC(2022,0,1,0,0,0,0);
const dateTimeFormat = new Intl.DateTimeFormat("de", {
timeZone: "UTC",
dateStyle: "medium",
timeStyle: "short",
}).format;
// Outputs "01.01.2022, 00:00", which is close to but
// not quite the same as your desired format
console.log(dateTimeFormat(testDate));
// Outputs your desired format, but may not be flexible across locales
const dateFormat = new Intl.DateTimeFormat("de", {
timeZone: "UTC",
dateStyle: "medium",
}).format;
const timeFormat = new Intl.DateTimeFormat("de", {
timeZone: "UTC",
timeStyle: "short",
}).format;
console.log(`${dateFormat(testDate)} ${timeFormat(testDate)}`);
¹ Remember that UTC is unchanging, it doesn't have daylight saving time.

how to represent MM/dd/yyyy, hh:mm tt using Intl.DateTimeFormat

I need to display the date on the format MM/dd/yyyy, hh:mm tt for the 'en' and 'es' locale. This approach works fine, but it displays the date as MM/dd/yy, showing only the last two digits for the year instead of the entrie year.
const en = new Intl.DateTimeFormat('en', { dateStyle: 'short', timeStyle: 'short', hour12: true }).format(new Date());
const es = new Intl.DateTimeFormat('es', { dateStyle: 'short', timeStyle: 'short', hour12: true }).format(new Date());
console.log('En', en, 'Es', es);
This approach
const en = (new Date()).toLocaleString('en');
const es = (new Date()).toLocaleString('es');
console.log('En', en, 'Es', es);
shows the full year, but it shows 24 hours format for the 'es' locale.
From here I have that when formatting large numbers of dates, it is better to create an Intl.DateTimeFormat object and use the function provided by its format property. And this might be the case. How can I get this working?
I need to display the date on the format MM/dd/yyyy, hh:mm tt for the 'en' and 'es' locale.
Using a language code for say "es" then modifying the format is the antithesis of the purpose of the Intl object. It's supposed to format values based on the language tag provided and the results used unmodified.
Specific formats should be created manually or with a library (essentially the same thing). Spanish and English use the same characters for numbers, so the same timestamp can be presented for both languages if they don't have day or month names, e.g.
There are already a huge number of questions on how to format a javascript date. The following is an example using the Intl object:
// MM/dd/yyyy, hh:mm tt using Intl.DateTimeFormat
function formatDate(date) {
let p = new Intl.DateTimeFormat('en',{
year:'numeric',
month:'2-digit',
day:'2-digit',
hour:'2-digit',
minute:'2-digit',
hour12: true
}).formatToParts(date).reduce((acc, part) => {
acc[part.type] = part.value;
return acc;
}, {});
return `${p.month}/${p.day}/${p.year}, ${p.hour}:${p.minute} ${p.dayPeriod}`;
}
console.log(formatDate(new Date()));
Presenting dates in month/day/year order to Spanish readers is likely to greatly confuse them (and the vast majority of English speakers too). Pages are presented in a particular language, so all dates, numbers, etc. should follow the conventions of that language.

How to convert from date.now to pacific time

On my current project, I have to implement elapsed time for each user and display it on the webpage.
However, using the date.now will return utc and I would like to get it in pacific time. I googled and researched through online but could not get it to work... Is there a way to convert from utc to pacific time?
You can do something like this:
const event = new Date(Date.now());
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
console.log(event.toLocaleDateString('us-PT', options));
Where "us" is the "United States" and "PT" is "Pacific-Time"
To see more go to MDN web docs Date.prototype.toLocaleDateString()
I see a few options you have at hand.
Option 1 - use an external library (moment / date-fns)
Consider using these libraries if your app is going to heavily rely on timezones, dates etc.
For example:
moment.tz(12345678, "America/Los_Angeles") // 12345678 being your Date timestamp
See more info here:
date-fns
moment
Option 2 - you need to use vanilla JS
Found a few answers on this thread, but I couldn't see any of them being long term reliable (because of savings time etc.) - I might be wrong about it, but I resort to date/time libraries when my app heavily uses the same.
This worked for me.
const date = new Date().toLocaleDateString('en-US', { timeZone: 'America/Los_Angeles' });
const time = new Date().toLocaleTimeString('en-US', { timeZone: 'America/Los_Angeles' });
const datetime = new Date().toLocaleString('en-US', { timeZone: 'America/Los_Angeles' });
Hope it helps others save time.

Detect timezone abbreviation using JavaScript

I need a way to detect the timezone of a given date object. I do NOT want the offset, nor do I want the full timezone name. I need to get the timezone abbreviation.
For example, GMT, UTC, PST, MST, CST, EST, etc...
Is this possible? The closest I've gotten is parsing the result of date.toString(), but even that won't give me an abbreviation. It gives me the timezone's long name.
A native solution:
var zone = new Date().toLocaleTimeString('en-us',{timeZoneName:'short'}).split(' ')[2]
console.log(zone)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
You can pass undefined instead of en-us to default to the browser's current locale.
moment-timezone includes an undocumented method .zoneAbbr() which returns the time zone abbreviation. This also requires a set of rules which are available to select and download as needed.
Doing this:
<script src="moment.js"></script>
<script src="moment-timezone.js"></script>
<script src="moment-timezone-data.js"></script>
<script>
moment().tz("America/Los_Angeles").zoneAbbr();
</script>
Returns:
'PDT' // As of this posting.
Edit (Feb 2018)
Evan Czaplicki has worked on a draft proposal to add a time zone API to browsers.
The Date object doesn't have a method for getting the timezone abbreviation, but it is implicit at the end of the result of toString. For example,
var rightNow = new Date();
alert(rightNow);
...will return something like Wed Mar 30 2011 17:29:16 GMT-0300 (ART). The timezone abbreviation can be isolated between parentheses:
var rightNow = new Date();
alert(String(String(rightNow).split("(")[1]).split(")")[0]);
The output will be the timezone abbreviation, like ART.
This works perfectly in Chrome, Firefox but only mostly in IE11. In IE11, timezones without straight forward abbreviations like "Indian Chagos Time" will return "ICT" instead of the proper "IOT"
var result = "unknown";
try{
// Chrome, Firefox
result = /.*\s(.+)/.exec((new Date()).toLocaleDateString(navigator.language, { timeZoneName:'short' }))[1];
}catch(e){
// IE, some loss in accuracy due to guessing at the abbreviation
// Note: This regex adds a grouping around the open paren as a
// workaround for an IE regex parser bug
result = (new Date()).toTimeString().match(new RegExp("[A-Z](?!.*[\(])","g")).join('');
}
console.log(result);
Result:
"CDT"
You can use the formatToParts method of Intl.DateTimeFormat to get the short time zone abbreviation. In certain parts of the world this may return strings like "GMT+8", rather than the abbreviation of an actual time zone name.
let timeZone = new Intl.DateTimeFormat('en-us', { timeZoneName: 'short' })
.formatToParts(new Date())
.find(part => part.type == "timeZoneName")
.value
console.log(timeZone)
Update for 2021
moment.js is now deprecated and they suggest using Luxon in new projects instead.
You can get a timezone abbreviation with Luxon like:
import { DateTime } from 'luxon'
DateTime.local().toFormat('ZZZZ') // => for ex: "PDT"
Note: The output format depends on the set locale. For more information see this answer.
I was able to achieve this with only moment.
moment.tz(moment.tz.guess()).zoneAbbr() //IST
Using contents from new Date().toString()
const timeZoneAbbreviated = () => {
const { 1: tz } = new Date().toString().match(/\((.+)\)/);
// In Chrome browser, new Date().toString() is
// "Thu Aug 06 2020 16:21:38 GMT+0530 (India Standard Time)"
// In Safari browser, new Date().toString() is
// "Thu Aug 06 2020 16:24:03 GMT+0530 (IST)"
if (tz.includes(" ")) {
return tz
.split(" ")
.map(([first]) => first)
.join("");
} else {
return tz;
}
};
console.log("Time Zone:", timeZoneAbbreviated());
// IST
// PDT
// CEST
You can use the Native Javascript date object.
Just hardcode the long timezone name 'America/Los_Angeles.
var usertimezone = 'America/Los_Angeles';
var usertimezoneabbreviation = new Date().toLocaleTimeString('en-us',{timeZone: usertimezone, timeZoneName:'short'}).split(' ')[2];
console.log(usertimezoneabbreviation); //PDT
If all else fails, you can simply create your own hashtable with the long names and abbreviations.
Updated for 2015:
jsTimezoneDetect can be used together with moment-timezone to get the timezone abbreviation client side:
moment.tz(new Date(), jstz.determine().name()).format('z'); //"UTC"
Moment-timezone cannot do this on it's own as its function which used to handle this was depreciated because it did not work under all circumstances: https://github.com/moment/moment/issues/162 to get the timezone abbreviation client side.
For a crossbrowser support I recommend using YUI 3 Library:
Y.DataType.Date.format(new Date(), {format:"%Z"});
It supports strftime identifiers.
For more information:
http://yuilibrary.com/yui/docs/datatype/#dates
I know the problem remains of differences between browsers, but this is what I used to get in Chrome. However it is still not an abbreviation because Chrome returns the long name.
new Date().toString().replace(/^.*GMT.*\(/, "").replace(/\)$/, "")
Not possible with vanilla JavaScript. Browsers are inconsistent about returning timezone strings. Some return offsets like +0700 while others return PST.
It's not consistent or reliable, which is why you need 3rd party script like moment.js (and moment-timezone.js) or create your own hashtable to convert between offsets and timezone abbreviations.
This is a tricky subject. From what I gather the timezone is not embedded as part of the Date object when it's created. You also cannot set the timezone for a Date object. However, there is a timezone offset you can get from a Date object which is determined by the user's host system (timezone) settings. Think of timezone as a way to determine the offset from UTC.
To make life easier, I highly recommend moment and moment-timezone for handling these things. Moment creates a wrapper object for Date with a nice API for all kinds of things.
If an existing date object is supplied to you through some parameter or something, you can pass it the constructor when creating a the moment object and you're ready to roll. At this point you can use moment-timezone to guess the user's timezone name, and then use moment-timezone formatting to get the abbreviation for the timezone. I would venture to say that most users have their timezone set automatically but you shouldn't rely on this for 100% accuracy. If needed you can also set the timezone you want to use manually before pulling the format you need.
In general when working with date and time it's best to store UTC in your database and then use moment js to format the time for the user's timezone when displaying it. There may be cases where you need to be sure the timezone is correct. For example if you are allowing a user to schedule something for a specific date and time. You would need to make absolutely sure that with a west coast user that you set the timezone to PDT/PST before converting to UTC for storage in your database.
Regarding the timezone abbreviation...
Here is a basic example to get the timezone abbreviation using moment and moment-timezone.
// if all you need is the user's timezone abbreviation you don't even need a date object.
const usersTimezoneName = moment.tz.guess()
const timezoneAbbr = moment().tz(usersTimezoneName).format('z')
console.log(timezoneAbbr) // PST (depending on where the user is)
// to manually set the timezone
const newYorkAbbr = moment(dateObj).tz('America/New_York').format('z')
console.log(newYorkAbbr) // EST
For displaying a specific date object with offsets for a specific timezone you can do this.
const xmas = new Date('December 25, 2017 16:20:00')
const losAngelesXmas = moment(xmas).tz('America/Los_Angeles')
console.log(losAngelesXmas.format("dddd, MMMM Do YYYY, h:mm:ss a")) // Monday, December 25th 2017, 4:20:00 pm
Try this function
function getTimezoneAbbreviation(date) {
// Convert the date into human readable
// An example: Fri Jul 09 2021 13:07:25 GMT+0200 (Central European Summer Time)
// As you can see there is the timezone
date = date.toString();
// We get the timezone matching everything the is inside the brackets/parentheses
var timezone = date.match(/\(.+\)/g)[0];
// We remove the brackets/parentheses
timezone = timezone.replace("(", "").replace(")", "");
// A new variable for the abbreviation
var abbreviation = "";
// We run a forEach dividing the timezone in words with split
timezone.split(" ").forEach((word) => {
// We insert the first letter of every word in the abbreviation variable
abbreviation += word.split("")[0];
});
// And finally we return the abbreviation
return abbreviation;
}
Try Google's Closure Class goog.i18n.DateTimeSymbols and their locale related classes.
Here is a JavaScript self-updating, 12-hour format date/time display that doesn't quite answer the question, however it may help others as it is related and builds on Stephen DuMont's solution and MDN link. W3 Schools had a very helpful tutorial, and real-time updates do not require page refresh.
Tests with the latest versions of desktop FireFox, Chrome, Opera, and Internet Explorer 11 all work. The "2-digits" hour only appears to prefix a zero for single values in IE, however the minutes return a 2-digit value reliably for all browsers. Tests with discontinued Windows Safari work although 12-hour format is ignored and seconds are not hidden.
The function includes the local timezone, as well adjustable options for fall-back languages, day and date display, and 12/24 hour format. Date and time were split to add the separating 'at' string. Setting only 'toLocaleTimeString' with select options will also return both date and time. The MDN pages can be referenced for options and values.
<!--
function dateTimeClock() {
var date = new Date();
document.getElementById('timedate').innerHTML = date.toLocaleDateString(['en-us', 'en-GB'], {
weekday: 'long',
month: 'long',
day: '2-digit',
year: 'numeric'
}) + ' at ' +
date.toLocaleTimeString(['en-us', 'en-GB'], {
hour12: 'true',
hour: '2-digit',
minute: '2-digit',
timeZoneName: 'short'
});
var t = setTimeout(dateTimeClock, 500);
}
function start() {
dateTimeClock();
}
window.onload = start;
//-->
<div id="timedate"></div>
import { tz } from 'moment-timezone';
import * as moment from 'moment';
const guess = tz.guess(true); // "Asia/Calcutta"
const zone = tz.zone(guess); // return Zone object
zone.abbr(new Date().getTime()) // "IST"
// once u pass timestamp it'll return timezone abbrevation.
try {
result = /.*\s(.+)/.exec(date.toLocaleDateString(navigator.language, {timeZoneName:'short' }))[1];
} catch(e) {
result = (new Date()).toTimeString().match(new RegExp("[A-Z](?!.*[\(])","g")).join('');
}
console.log(result);

Categories