How to make a DateTime string that changes depending on time zone? - javascript

I'm in the middle of writing a website, and I got this marvellous idea. I would have my contact page change depending on the time zone it was viewed from.
Examples:
When viewed in the local time-zone (GMT +1):
I can be reached between 08:30 and 17:30
When viewed in New York (GMT -5):
I can be reached between 03:30 and 12:30
In San Francisco (GMT -8):
I can be reached between 00:30 and 09:30
In Beijing (GMT +8):
I can be reached between 16:30 and 01:30
... You get the idea.
I'm not sure where I should start. I know of moment.js but I'm not sure if it's suitable for this purpose, 'specially considering the fact that I want this to be automatically determined by the user's current location.
I'm using Node.js with Express.js for the server, and jQuery on the client-side. Any help?

You can create Date object with UTC time and get local time from it.
// args are in UTC time
function toLocalTime(hours, minutes){
var d = new Date(Date.UTC(0, 0, 1, hours, minutes, 0));
return [d.getHours(), d.getMinutes()].map(function(x){
return ('0' + x).slice(-2);
}).join(':');
}
"I can be reached between " + toLocalTime(07, 30) + " and " + toLocalTime(16, 30)

Related

Find next occurrence of a time in a non-local timezone (in this case, PST)

I want to get how far away is the next occurence of a particular PST time regardless of the client's timezone.
This would be trivial if the time were in UTC but I don't know how to do it in PST keeping in mind the observance of daylight savings time.
Eg. 4 PM PST would be 11 PM UTC since it is right now summer.
I would prefer not to have to manually input the dates of daylight saving time.
I am happy to use a library if this is not possible without one.
// returns the number of milliseconds from the current time until the specified time in PST.
function getTimeUntil (hour, minutes = 0, seconds = 0)
{
// implementation needed
}
The following is an explanation of why this is likely a duplicate of How to initialize a JavaScript Date to a particular time zone.
PST (presumably US Pacific Standard Time) is a timezone with a fixed offset, UTC -8. Places that observe PST and have daylight saving typically call that offset Pacific Daylight Time (PDT), which is UTC -7.
PST might also be Pitcairn Standard Time, which is also UTC -8 and observed all year round on Pitcairn Island. Converting PST to UTC is achieved by adding 8 hours.
However, likely you want to work with times and dates for a place that observes US PST in winter and US PDT in summer, e.g. Los Angeles. In that case you can use a library like Luxon or date.js that allows creating dates based on a timestamp and specified IANA representative location such as "America/Los_Angeles". If that is the case, then see the link above.
My implementation:
// returns the formatted time from the current time until the specified time in PST.
function getTimeUntil (hour, minutes = 0, seconds = 0)
{
let future = luxon.DateTime.now().setZone('America/Vancouver').set({
hours: hour,
minutes: minutes,
seconds: seconds
});
let now = luxon.DateTime.now().setZone('America/Vancouver');
if (future < now)
{
future = future.plus({ days:1 });
}
return future.diff(now, ["hours", "minutes", "seconds"]);
// implementation needed
}
console.log(getTimeUntil(13, 0, 0).toObject());
<script src="https://cdn.jsdelivr.net/npm/luxon#2.0.1/build/global/luxon.min.js"></script>

getHours() at 9pm returns 20, then after DST returns 21. How to always return the same number

I'm running code in the backend of google sheets, and I have a function on an every minute timer that then determines if it's the right time for it to run. I need it ran at precise times. I had it working properly to trigger at 9:05pm, but now that daylight savings has passed it's triggering at 8:05pm.
How do I fix this without having to manually change the value after every DST change? Is there a way for getHours() to return the same number at the same time throughout the year?
getUTCHours() is probably a better bet if you want consistency as there will be no DST.
You can use getUTCHours() to get a consistent number of hours without concern for daylight savings time.
It depends on what you mean by consistent. If you're not looking for the same time each day in local time but for the event to happen ever 24 hours then I suggesting using UTC time.
var halloweenNight = new Date('October 31, 2019, 21:00:00 EDT')
var thanksgivingNight = new Date('November 28, 2019, 20:00:00 EST')
console.log('Halloween EDT: ' + halloweenNight.toString())
console.log('Thanksgiving EST: ' + thanksgivingNight.toString())
console.log('Halloween UTC: ' + halloweenNight.toUTCString())
console.log('Thanksgiving UTC: ' + thanksgivingNight.toUTCString())
console.log('Halloween local hours: ' + halloweenNight.getHours())
console.log('Thanksgiving local hours: ' + thanksgivingNight.getHours())
console.log('Halloween UTC hours: ' + halloweenNight.getUTCHours())
console.log('Thanksgiving UTC hours: ' + thanksgivingNight.getUTCHours())

Store date as if they were entered in a specific timezone

I am using Moment. I need users to enter a date, and make sure that that's always the time for Australia/Perth, regardless of what the browser is set as.
For example, assume the computer is set as Sydney time (which right now is +3 but in winter it's +2). I want the user to enter a date/time, and make sure that that date/time is stored as Perth's time.
Note that visualising the correct date isn't an issue (with moment.tz). What I am worried about, is the date object creation which would need to happen providing a time, and forcing the browser to pretend that they are in that timezone.
I need this to work regardless of daylight savings etc.
UPDATE: this is what I want to achieve:
// MY CURRENT TIMEZONE IS SYDNEY, CURRENTLY PERTH + 3 BUT +2 IN SUMMER
// IN PERTH IT's 10:11AM, and *THAT* is the time I am interested in
// storing, not 13:11:58
var d = new Date()
// => Wed Nov 28 2018 13:11:58 GMT+1100 (Australian Eastern Daylight Time)
// NOTE: the date 13:11:58 SYDNEY time. I don't want this.
// I MUST pretend that users entered the date with their timezone
// is in Perth
// So...
// Create a date string that exclude original timezone and includes new timezone
perthDateString = moment(new Date()).format('YYYY-MM-DDTHH:MM:ss') + '+0800'
// => "2018-11-28T13:11:58+0800"
// Make a new date object using the tinkered date string
var newD = new Date(perthDateString)
// Display the date. Note: the time is "wrong" (since it displays
// a time that is 3 hours ahead), but it's actually the correct
// answer since 'd' is meant to be Perth time in the first place
newD
// => Wed Nov 28 2018 16:11:58 GMT+1100 (Australian Eastern Daylight Time)
// Display the date as the Perth time
moment.tz(newD, 'Australia/Perth').toString()
// => "Wed Nov 28 2018 13:11:58 GMT+0800"
However:
in perthDateString = moment(new Date()).format('YYYY-MM-DDTHH:MM:ss') + '+0800', I would like to specify Australia/Perth, rather than '+0800'
I feel uneasy with dealing with dates by chopping/concatenating strings
I wonder if EVERY browser will be able to parse the date returned by .format('YYYY-MM-DDTHH:MM:ss') + '+0800' or if I am going to have surprises -- especially when/if I have a solution so that I use Australia/Perth instead
If you are anywhere in the world (say, Sydney or Tokyo), and the local time is "12:30", but you want to store the same time-of-day ("12:30") as if you were in Perth -- you can use the moment-timezone package together with moment.
For example, this snippet will give you a moment for "12:30" in Perth:
let x = moment.tz('2019-01-01T12:30:00', 'Australia/Perth')
console.log(x.format()); // Show that it is 12:30 in Perth time
console.log(new Date(x)); // Generate Date for that time
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="http://momentjs.com/downloads/moment-timezone-with-data.js"></script>

Operating in the end user's timezone with momentjs

I'm in EDT and my end user is in PDT. I'd like my WebApp to operate as if it's running in the end user's timezone (e.g. even if they travel it's to show the time back home). The timestamps coming from the Java server are formatted to include the end user's timezone e.g. "Mon Oct 27 06:57:00 PDT 2014", and I also have the end user TZ string e.g. "America/Vancouver" in a config file. I'm using native Date() and it's displaying the right time for the user, but I can't use it to compare times with times in the client. I'm looking to change to moment.js, but I can't figure out how to get it to do what I want. Basically, given the above timestamp, I want to be able to call m.hour() and get 6 back. I also want to be able to get the day of the year in end user time (both "now" and for a timestamp), and see how far back the last timestamp is from the current time, in minutes. Here is my failed attempt:
var d = "Mon Oct 27 06:57:00 PDT 2014";
var ds = d.split(/ /).slice(1).join(' '); // eat "Mon "
var m = moment.tz(ds, "MMM D HH:mm:ss Z YYYY", "America/Vancouver");
alert("" + m.hour()); // 23 ??? Want "6"!
var n = moment.tz("America/Vancouver");
var df = n.diff(m, 'minute');
alert(m.format() + "\n" + n.format() +
"\n" + df + " minutes ago");
Fiddle: http://jsfiddle.net/up628qbq/
Thanks!
Use a lower-case z in the format string instead of the upper-case Z. That will match the time time zone abbreviation characters.
Note that this won't actually interpret the abbreviation as a particular offset. This is primarily because abbreviations can be ambiguous. (There are 5 different meanings of "CST"). Because of this, some values during a DST fall-back transition may be interpreted incorrectly.
For example, in the Pacific time zone, there are two instances of 1:00 AM on November 2 2014. The first is in PDT (-7) , and second is in PST (-8). Even though you provided an abbreviation, moment won't use it to disambiguate. If you want to be certain of which instance you are working with, you would need a numeric time zone offset to be included and parsed with Z.
Also, you can use ddd for the weekday name instead of splitting and slicing.
Thank you Matt! I don't have enough reputation to "vote up", so I have made the changes you recommend (remove split and add ddd format, change Z to z) in the fiddle: http://jsfiddle.net/up628qbq/1/

How to convert UTC date/time to EST date/time

I'm using the following code to get the current UTC time in the correct format, but the client has come back and asked that the timestamp now be in EST instead of UTC. I have searched Google and stackoverflow, but can't find an answer that works with my existing code.
var currentdate = new Date();
var datetime = currentdate.getFullYear() + ":"
+ ("0" + (currentdate.getUTCMonth()+1)).slice(-2) + ":"
+ ("0" + currentdate.getUTCDate()).slice(-2) + ":"
+ ("0" + currentdate.getUTCHours()).slice(-2) + ":"
+ ("0" + currentdate.getUTCMinutes()).slice(-2) + ":"
+ ("0" + currentdate.getUTCSeconds()).slice(-2);
What we are trying to do is set a consistent timestamp to EST regardless of where the browser is located in the world, hence the use of the UTC time originally.
Thanks!
A few things...
The term "EST" can be used for either Eastern Standard Time in North America, or Eastern Standard Time in Australia. Most time zone abbreviations are not unique, so you should be more specific.
EST also does not define a time zone in its entirety. It only defines part of the time zone that is used during the winter months. The other half is called Eastern Daylight Time, abbreviated EDT. Your client probably meant "Eastern Time", which would need to take both into account.
The typical way to define time zones is as an identifier from the IANA time zone database. You can read more about it in the timezone tag wiki. For example, if your client meant Eastern Time in the United States, then your time zone is "America/New_York".
JavaScript inherently doesn't know anything about time zones, other than it's own and UTC. (The link that bjb568 gave does not handle daylight saving time properly.) In order to work with them on the client, you will need to use one of the libraries I list here.
Your current code is a bit strange in terms of output. Usually colons are used for separating only the time, and you are using them for all parts. Anyway, it's not converting anything, it's just outputting UTC.
You might do well with a library like moment.js and it's moment-timezone add-on. For example:
moment().tz("America/New_York").format("YYYY-MM-DD HH:mm:ss")
The following answer (copied from this link on this site) worked very well for me. It easily and correctly converted the following Zulu time (which is same as UTC) "2014-10-09T20:30:54Z" to South African time.
var tmpDate = New Date("enter any valid Date format here")
The javascript Date() function will automatically convert it to your local time.
Example:
var tmpDate = new Date("Fri Jul 21 02:00:00 GMT 2012")
alert(tmpDate);
//Result: Fri Jul 20 22:00:00 EDT 2012
Below line will work:
console.log(moment().tz("America/New_York").format("YYYY-MM-DD HH:mm:ss"))

Categories

Resources