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.
Related
I want to get the current hour (e.g. 13 if the time is 13:45) in the time zone "Europe/London", no matter the user's own time zone.
It only needs to work in modern browsers, and it's fine if the user's browser doesn't happen to handle this time zone – it's for a bit of progressive enhancement where I'm fine wrapping it in a try/catch and doing nothing if it fails.
The following was the best I could come up with.
const timeZone = "Europe/London"
const dateTimeFormat = new Intl.DateTimeFormat("en-GB", { timeZone, hour: "numeric" })
const hour = parseInt(dateTimeFormat.formatToParts(new Date)[0].value, 10)
Is there a simpler way?
You can use toLocaleString() method
const hour = new Date().toLocaleString("en-GB", { timeZone: "Europe/London", hour: "numeric" });
console.log(hour)
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 need to take an hour and convert it to local time as such :
const dataDate = '07:08'
const utcDate = new Date(dataDate);
console.log(utcDate)
there are a few problems with my approach
this only works if i add a date too
this converts to utc
I need to only convert the hour to local time, I also need to parse it to something like this :
[parseInt(hour), 0, 0, 0].map(function (x) { return parseInt(x, 10); })
To give more context, I need to create a shareable calendar with a specific schedule, and the user can set the specific hours for some event to be displayed.
If you have access to the full date
Considering your use-case is that of a shareable calendar, I'm assuming you
have access to the full UTC date. If that's not the case, skip to the next
section.
// The important thing is getting a `Date` object. The timezone in the timestamp
// doesn't really matter at this point. It will be handled internally anyway.
const date = new Date("2011-11-11T07:08:00Z");
Once you have the date object, if all you really want to get is the hour,
you can do so with the methods below. But note that you should probably use the same method for getting not only the hours, but any part of the date or time throughout your application.
const utcHour = date.getUTCHours(); //> 7
// For the hour according to the timezone configured in the RUNTIME
// environment (e.g. the user's browser, if running on the client side):
const runtimeHour = date.getHours(); //> 8 (depends on the runtime timezone)
// For an arbitrary timezone, in case you have the user's timezone stored in
// a config you could use the `.toLocaleTimeString()` method.
// Note that this method is VERY slow (~6000 times slower than `.getHours()`
// for example in a quick benchmark I ran in my machine on Node 16). You
// should probably be careful about how often this is being called (e.g. in
// loops or in a frontend component that is frequently updated/rendered).
const tzHour = Number(date.toLocaleTimeString("en", {
hour: "numeric", // omit minutes and seconds
hour12: false, // force it to be 0-23
timeZone: "America/Sao_Paulo" // set the user's timezone
})); //> 5
Which one you should use really depends on your exact implementation. You might also want to check this answer that further explains how time zones are handled by Date.
NOTE: the .toLocaleTimeString() method depends on the
Intl.DateTimeFormat API. Check Date.prototype.toLocaleTimeString() at MDN
for a compatibility table.
Note about manually calculating time offsets
You need the date in order to reliably adjust the time.
If you don't have the date for some reason, you could do so but that would
mean quite some work and it would never really be reliable, as you would not be
able to factor in Daylight Saving Time adjustments, for example.
Also keep in mind that some timezones operate on fractions of an hour:
+XX30: Asia/Tehran, Asia/Kabul, Australia/Adelaide...
+XX45: Australia/Eucla
Australia/Lord_Howe has a Daylight Saving Time adjustment of 30 mins;
Depending on the requirements of your application, calculating this manually
might not be as simple as you expect. I would recommend to delegate these
calculations to the internal Date implementation (as shown in the previous section) instead of trying to adjust the time manually (keep in mind you would have to handle overflows from min → hour → day → month → year).
About parsing the time string
As for the parsing of the time string, you mentioned in your question, you could do something like:
const rawTime = "07:08";
const [hour, minutes, seconds = 0] = rawTime.split(":").map(Number); //> [7, 8, 0]
// or if you only care about the hours
const hour = Number(rawTime.split(":", 1)); //> 7
// or you could also use a quirk of `parseInt()`, as it ignores everything
// starting at the first non-numeric character:
const hour = parseInt(rawTime); //> 7
If you instantiate a new date with new Date() the retuned value is current date/time in UTC timezone.
You can then set a specific hour/minute to that using Date.setHours() and Date.setMinutes().
Finally you can convert that UTC date to local date via Date.toLocaleDateString()
So I would do something like this for your case:
const date = new Date();
const [hour, minute] = '7:28'.split(':')
const options = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
};
date.setHours(hour);
date.setMinutes(minute);
console.log(date.toLocaleDateString('en-US', options));
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 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')