Get the web User's timezone as string - javascript

I am making a site, and where the users will be uploading questions and answers in it. Now I need to get the user's timezone which i can store it in variable $TimeZoneNameTo instead of just "Asia/Kathmandu". is there anyway, where the time zone as a string will be detected and stroed in variable $TimeZoneNAmeTo, so for any user of any timezone, the datetime will be converter to his/her timezone instead of UTC while displaying.
$TimeZoneNameFrom="UTC";
$TimeZoneNameTo="Asia/Kathmandu";
echo "uploaded on".$upload_date;
echo"<br>";
echo date_create($upload_date, new DateTimeZone($TimeZoneNameFrom))
->setTimezone(new DateTimeZone($TimeZoneNameTo))->format("Y-m-d H:i:s");

If all you want to do is present times based on the user's system settings, then just send UTC time values to the client. The value should be milliseconds since 1970-01-01T00:00:00Z. UNIX uses seconds since the same epoch, so you just need a UNIX UTC timestamp multiplied by 1000:
var newLocalDate = new Date(UNIXutcTimeValue * 1000);
Now just present it in a user readable form, say using Date.prototype.toLocaleString:
alert(newLocalDate.toLocaleString());
e.g. 2014-06-06T12:00:00Z is 1402056000 seconds or 1402056000000 milliseconds, so in Safari:
alert(new Date(1402056000000).toLocaleString()) // 6 June 2014 20:00:00 AWST
Of course you can always use Date methods to format the string anyway you want.

Answering the question you ask :
On modern browsers you can fetch the timezone client side using
var tz = Intl.DateTimeFormat().resolved.timeZone;
If your browser doesn't have Intl (IE10- and Safari), then it's a little more complicated. I made a small library for that using moment.js : https://github.com/Canop/tzdetect.js
Answering the problem you have :
Most of the times you don't have to know the client's timezone and you can simply let his browser format a UTC timestamp you send. See RobG's answer.

Related

What do we mean when we say store time as UTC? [duplicate]

This question already has answers here:
When is it ok to store datetimes as local time rathen than UTC?
(1 answer)
How to store repeating dates keeping in mind Daylight Savings Time
(1 answer)
Managing timezone & DST issue for javascript application
(1 answer)
java Calendar, Date, and Time management for a multi-timezone application
(1 answer)
Closed 3 years ago.
I have a scheduling application, with a calendar that I build from scratch.
As a lawyer, you should be able to configure your available times for booking, like below:
A lawyer's availabilities in Australia
:
1- 10/01/2020, from 07:00am to 08:am
...
Here's what I do :
1- Get the epoch number of the entered date in Javascript :
const dateFrom = new Date(firstOfJanSevenAm).getTime() // 1578600000000
// Fri Jan 10 2020 07:00:00 GMT+1100 (Australian Eastern Daylight Time)
const dateTo = new Date(firstOfJanEightAm).getTime() // 1578603600000
// Fri Jan 10 2020 08:00:00 GMT+1100 (Australian Eastern Daylight Time)
2- Send this to NodeJS server and save it MongoDB
Mongoose.save({
from:dateFrom, //1578600000000
from:dateTo //1578603600000
})
3- Represent it inside the Calendar :
<div>{format(from, 'HH:mm')}</div>
Everything is working as expected.
Now, this lawyer is traveling to the US and he's in a coffee shop using the US local time ( any city), he opens the Calendar, he wants to add some availability, but in Sydney time. I need to provide him with a timezone dropdown so he can tell me that he wants the new date to be based on his home, Syndey.
Question :
1- Do I save the date as I'm doing ( as a number ), and save the timeZone separately next to it, and when representing it, just apply the timeZone?
Mongoose.save({
from:dateFrom, //1578600000000
from:dateFrom //1578603600000
currentTimeZone : 'America/Costa_Rica',
desiredTimeZone: 'Australia/Sydney'
})
<div>{formatWithTimeZone(from, 'HH:mm',desiredTimeZone)}</div>
Is this all I have to do? Or am I naively missing something that is going to trip me down the road?
And back to my original questions, where do I do the whole "always store time as UTC" thing?
All I've realized is, when I use the library that I'm using date-fns-tz and try to convert the user entered date to UTC, I get exactly the same output :
const dateFrom = new Date(firstOfJanSevenAm).getTime() // 1578600000000
const dateFromUTC = zonedTimeToUtc(dateFrom,currentTimeZone) // 1578600000000
// currentTimeZone is America/Costa_Rica, when he is in Costa Rica's caffee shop.
enter code here
1578600000000 === 1578600000000 = true
So why do I get the same output when converting the entered date, to it's UTC date?
I am going to give you an answer decoupled from the technical implementation.
Let's think by contradiction, you have a lawyer living in Australia and another living in Switzerland, what happens if you decide to store time in their preferred location?
You then need to save two information: the time of course (11 am) but it's relative so you also need to store the timezone (11 am in Australia) or (1 pm in Switzerland)
Now what happens if your lawyer travels to France? Do you want to update all his calendar information? 11 am is not 11 am anymore.
UTC solves this problem, you just need to store 11 am or 1 pm. UTC is arbitrary absolute, universal by convention.
So your backend/database should store this kind of information in UTC, always. And you need a way to know your user's timezone, maybe it's possible to update it using a web interface and it could be stored in a user database or just cookies. Maybe you want to derive it yourself by using your user's location, IP, browser's language, whatever.
Now that you know his timezone, your server can send UTC (absolute) time to the client and the client can seamlessly display the correct (relative) time.
The client deals with relative time, the server always makes it absolute.
So why do I get the same output when converting the entered date, to it's utc date?
The value returned by getTime is the number of milliseconds since 1 January 1970 00:00:00 according to universal time.
Therefore, UTC and getTime both represent a moment in time using the same universal timezone.
Do I save the date as I'm doing, and save the timeZone separately next to it, and when representing it, just apply the timeZone?
Don't save the timezone with the date. Just save the date in universal time. If you need to save timezone. That should go in user settings. However, you can guess the timezone; therefore, you don't need to save this information.
Saving the date
When you do save the date to the database, it should be represented by a UTC time string or by a UNIX timestamp, both options demonstrated below.
UNIX timestamp
UNIX timestamp should be in seconds. getTime returns milliseconds. You can just divide by 1000 to get the UNIX timestamp.
const unixTimestamp = new Date('December 17, 1995 03:24:00').getTime() / 1000;
UTC Date string
const utcDate = new Date('December 17, 1995 03:24:00').toUTCString();
Displaying the date
When you get the date from the back-end, then, converted it to the correct timezone.
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone
const fromUnix = utcToZonedTime(1578423483, timezone)
const fromUtc = utcToZonedTime('Fri, 02 Feb 1996 03:04:05 GMT', timezone)
Closing thoughts
Dealing with timezones can be confusing. I am not to familiar with date-fns-tz. If you have the option, I would suggest migrating to Moment.js. Moment.js is the de facto standard JavaScript library these days - I highly recommend it.

How to change only timezone without modifying the time in momentz

I have date and time in 2016-06-21T10:00:00-07:00 format which represets 06/21/2016 5 PM in PST, I just want to change this to 06/21/2016 5 PM in EST and vice versa. How can I do it with momentz?
JSFiddle
debugger;
var dateTime = moment('2016-06-21T10:00:00-07:00');
var newDateTime = dateTime.clone();
newDateTime.tz('US/Eastern');
//dateTime = dateTime.utc();
console.log(dateTime.utcOffset());
console.log(newDateTime.utcOffset());
console.log(newDateTime.utcOffset() - dateTime.utcOffset());
//console.log(utc.format());
dateTime = dateTime.add(newDateTime.utcOffset(), 'minutes');
console.log(dateTime.format());
console.log(new Date(Date.parse(dateTime.format())).toJSON());
EDIT:
given input = 2016-06-21T08:00:00-07:00 (PST)
expected output = 2016-06-21T08:00:00-04:00 (EST)
So when I convert that to UTC then it should become
2016-06-22T15:00:00Z for PST
2016-06-22T12:00:00Z for EST
I think you are confused about how ISO8601 format works. This format always represents local time with a time zone offset. Thus 2016-06-21T10:00:00-07:00 represents June 21 2016 at 10 AM in a timezone that is currently UTC-7 (this could be US pacific, among many others).
It sounds like you want to take the local time, but put it in a new timezone. This opens up some interesting questions about why you are receiving the date in the format that you are. If the date is meant to be interpreted as an exact point on the global timeline, then the format you are receiving it in is good. If however, the date is meant to be interpreted as a local time (not relative to UTC), it might be worth considering the possibility that the format of the date needs to be changed at the source. For instance, if you are making an ajax request to an API, and it is returning a date in this format, but that date actually has no relationship to UTC, it would be good to try to change that API to only send the local time (without the offset). If you were able to do that, then the following code would work:
moment.tz('2016-06-21T10:00:00', 'America/New_York').format()
"2016-06-21T10:00:00-04:00"
If you are unable to do that, or if the date is meant to be interpreted as an exact point on the global timeline, but you wish to ignore that in your specific use case, that can be done. You will need to specify a parse format that ignores the timezone offset on your initial time stamp. The code would be as follows:
moment.tz('2016-06-21T10:00:00-07:00', 'YYYY-MM-DDTHH:mm:ss', 'America/New_York').format()
"2016-06-21T10:00:00-04:00"
You might benefit from the material in this blog post, as it covers how ISO8601 format works, and how all of moment's constructor functions work.
Checkout moment().utcOffset() You can pass in the offset as parameter to this function and the date would use that locale.
Assuming you know beforehand the utcOffsets required which in your case are -420 and -240 or -300(EST with DayLightSaving). Below can be done
var dateTime = moment('2016-06-21T10:00:00-07:00');
dateTime.utcOffset(-420).format();
"2016-06-21T10:00:00-07:00"
dateTime.utcOffset(-240).format()
"2016-06-21T13:00:00-04:00"
NOTE: With -04:00, it should 13:00:00 and not 07:00:00 - http://www.timeanddate.com/time/zones/est
EDIT: This answer was posted to the earlier version of question, where same time was needed in different timezones. If it is incorrect, kindly please elaborate on how it is.
Thanks!

how to adjust timestamp difference of client and server?

Which is the best way to display the "sent time" of message to user?
Is saving with "server side time() function" better or saving with "client side getTime()" and updating that value with ajax is better?
if server and client are in different timezones, either set the timezone to one of them to be same as the other or use a timezone difference (e.g +2 hours) and adjust all dates accrordingly to one of them (by adding/subtracting the timezone diff)
alternatively the client can always display dates as sent by the server and you are done
e.g if you have the server timezone difference just display it in the client as such (and you dont need anything else, if that is good for your use case)
2016-01-03 17:12:00 (+1 GMT)
For your example:
add the timezone diff (+ 1 hour), in the client (or the server, but not both)
e.g in the server (php DateTime)
$server_date = date('Y-m-d H:i:s');
$client_date = DateTime::createFromFormat( 'Y-m-d H:i:s', $server_date );
$client_date->add( new DateInterval('PT'.(60*60).'S') ) // + 1 hour
$client_date = $client_date->format('Y-m-d H:i:s');
or in the client (js use a library like moment.js or DateX)
var client_date = new Date(timestamp(server_date, 'Y-m-d H:i:s')+60*60*1000); // + 1 hour;
// timestamp is supposed to parse the date and return a unix timestamp in milliseconds
// for example if you use DateX, you can do:
// client_date = new DateX(DateX.fromString(server_date,'Y-m-d H:i:s').getTime()+60*60*1000).format('Y-m-d H:i:s');
A third option is for the server to always sent UTC (GMT) dates and let the client convert them to local/timezoned dates (sth similar to the above, only the client uses its own timezone offset instead of being hardcoded, e.g +1 Hour)
The server is the only machine you have control over, so it is the only machine you can rely on. But beware of daylight savings time.
I'd recommend storing all dates on the server in UTC, and then converting to local time in the browser. Doing this will also help you account for daylight savings time changes, which occur at different times around the world.
To illustrate this, if you were doing this server side, then the following C# code converts UTC to the local time, accounting for daylight savings times:
DateTime utc = DateTime.UtcNow;
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone);
I know this is a PHP question, but I hope this code helps.

In Javascript / NodeJS return current date adjusting for timezone, then find UTC equivalent of user's time at 6am

Sorry if the title is a little convoluted. I'm bashing my head against the floor with times in NodeJS / Javascript. I can get the current UTC time like this:
var currentTime = Date.now();
I can get the current time for a user who is, for example, in the -3 timezone like this:
var offsetTime = Date.now() + (numTimeZone * 3600000);
But how do I get the local user time at, say, 6am, converted to UTC?
Practical application:
What I'm trying to do is create an auto-emailer which sends an email to a user at 6am in their local time. My server is in one timezone and they will be in another, so I'm trying to standardise it against UTC so every minute I can set my server to check the currentUTC time, then check what the user's 6am time is converted to UTC (local6am), and if the currentUTC > local6am then an email should be sent.
What's the best way to achieve this? Preferably without using a library if possible.
Utc to Local
moment.utc('2014-02-19 05:24:32 AM').toDate();
Local to utc
Read this documentation.
MomentJS is parsing the date as a locale date-time. If no hour is given, it is assuming midnight.
Then, you convert it to UTC, so it is shifted, according to your local time, forward or backwards. If your are in UTC+N, then you will get the previous date.
moment(new Date('02-19-2014')).utc().format("YYYY-MM-DD HH:mm").toString()
moment(new Date('02-19-2014 12:00')).utc().format("YYYY-MM-DD HH:mm").toString()
(or)
You can try this:
moment.utc('07-18-2013', 'MM-DD-YYYY')
moment.utc('07-18-2013', 'MM-DD-YYYY').format('YYYY-MM-DD')
You do not need to call toString explicitly.

How to create Javascript Date() object given Country ISO code?

Consider I'm from India and my Country ISO code is IN or IND or 356 (http://en.wikipedia.org/wiki/ISO_3166-1). How could I generate a JavaScript Date object with that? That is, in IST.
In Python, we have astimezone(). Anything similar to that is available in JavaScript?
PS: jQuery or any trusted third party API is allowed.
JavaScript in the browser is not a timezone aware language. It has the ability to work with only two timezones: UTC and local timezone where local timezone depends on the timezone of the Browser or the Operating System that the Browser runs on.
If your browser (and your user's browser) is set to IST, then all dates will display in IST. If your browser is not set to IST, then you're sort of out of luck.
Now, you can do some tricks. For example, you can do the following:
var d = new Date(); // creates a date in user's local timezone
var istD = new Date(d.getTime() + (d.getTimezoneOffset() + 330) * 60000)
// 330 is the IST offset (5h 30m == 330m)
istD is now a date object that will "print the date in IST". Note that this date object is still in the user's local timezone, but as long as you don't display the timezone part, it will appear to be in IST.
There is a small problem with Daylight Saving Time. Since IST does not have DST, this problem is minimized, but still exists if the user's local timezone has DST and you are just a few hours off from the DST offset. You might be able to play around with the Date.getUTC* functions to circumvent the DST issues, however always remember that there is no way to correctly do timezones in clientside JavaScript. There is no library in existence today that correctly handles all TimeZone rules, including Daylight Savings rules for all historical dates.
You can set the date with UTC and then you can convert it into LocaleString. You can see Date.prototype.toLocaleString() for more refrence.
And you can also see the question asked on stack overflowHow do I display a date/time in the user's locale format and time offset?.
Thanks
There is no directly API.But you can coding it by your self.
<html>
<body onload="getTimeByTimeZone(5.5)">
<script type="text/javascript">
function getTimeByTimeZone(offset){
var d = new Date()
localTime = d.getTime();
localOffset=d.getTimezoneOffset()*60000;
utcTime=localTime + localOffset;//get utc time
st=utcTime+3600000*offset;//get the specified timezone time
stime=new Date(st);
document.write("The specified time is :"+stime.toString());
}
</script>
</body>
</html>
Hope this code is helpful to you.

Categories

Resources