Convert UTC time to specific zone - javascript

I have the following data:
var currentTime: 2013-07-11 15:55:36+00:00
var currentTimezone: Africa/Asmera
I need a way to convert the currentTime in UTC to a new time based on currentTimezone.
I've looked into Timezone.js and I'm having trouble implementing it (the directions on the site are a little ambiguous)
The code for the function I'm intending on using is included. Thanks :)
<script>
$("#storeTime").click(function(){
storeCurrentTime();
})
$("#getTime").click(function(){
retrieveTime();
})
$("#storeTimezone").click(function(){
var yourTimezone = $('#timezone-select').find(":selected").text();
tz = yourTimezone.toString();
storeCurrentTimezone(tz);
})
$("#convertTime").click(function(){
//get the most recent UTC time, clean it up
var currentTime = $('#RetrievedTime').html();
currentTime = currentTime.split(": ")[1];
$('#convertedTime').html("Converted Time: " + currentTime);
//get the saved timezone
var currentTimezone = $('#storedTimezone').html();
})
</script>

You're going to need to know the timezone offset, so some sort of dictionary with strings to numbers.
// assuming your dictionary says 3 hours is the difference just for example.
var timezoneDiff = 3;
Then you can just make a new time like this
// Assuming you have the proper Date string format in your date field.
var currentDate = new Date(currentTime);
// Then just simply make a new date.
var newDate = new Date(currentDate.getTime() + 60 * 1000 * timezoneDiff);
Update
I've written a javascript helper for this which you can find at:
http://heuuuuth.com/projects/OlsonTZConverter.js
I pulled the timezone data from the wikipedia page https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Usage is as follows once included the script.
var offset = OlsonTZConverter.GetUTCOffset("Africa/Asmera");
or if there is Daylight Savings in effect:
var offset = OlsonTZConverter.GetUTCOffset("Africa/Asmera",true);
These will throw if you pass an invalid timezone, but you can check if a timezone is valid with:
var isValid = OlsonTZConverter.Contains("Africa/Asmera");
or just look at the entire dictionary with:
var tzDict = OlsonTZConverter.ListAllTimezones();
Hope this maybe saves someone some time sometime :).

Related

How can I get the timestamp in javascript from a string including the timezone db name

I got the following string: "2022/05/01 03:10:00" and I need to create a Date object forcing it to use Chile's UTC offset.
The problem is that because of Daylight saving time (DST) the offset changes twice a year.
How can get that Date object, for example, using the "America/Santiago" TZ db name?
Something like:
new Date("2022/05/01 03:10:00" + getUtcOffset("America/Santiago")).
function getUtcOffset(tzDbName) {
..
}
Returns -3 or -4, depending the time in the year.
EDIT:
I ended using a nice trick for determining if DST was on or off.
reference
const dst = hasDST(new Date(strDate));
function hasDST(date = new Date()) {
const january = new Date(date.getFullYear(), 0, 1).getTimezoneOffset();
const july = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
return Math.max(january, july) !== date.getTimezoneOffset();
}
Then I could create the date with the correct timezone depending on that variable.
if (dst) {
let d = new Date(strDate + " GMT-0300");
return d;
} else {
let d = new Date(strDate + " GMT-0400");
return d;
}
Thanks everyone!
EDIT2:
I finally found a very nice library that does exactly what I was looking for:
https://date-fns.org/v2.28.0/docs/Time-Zones#date-fns-tz
const { zonedTimeToUtc, utcToZonedTime, format } = require('date-fns-tz')
const utcDate = zonedTimeToUtc('2022-05-05 18:05', 'America/Santiago')
This has been discussed before here.
Haven't tested it, but it appears that the simplest solution is:
// Example for Indian time
let indianTime = new Date().toLocaleTimeString("en-US",
{timeZone:'Asia/Kolkata',timestyle:'full',hourCycle:'h24'})
console.log(indianTime)
You can check the link for more complex answers and libraries
Generals notes
To get the time zone name use:
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)
To get the difference from UTC (in minutes) use:
var offset = new Date().getTimezoneOffset();
console.log(offset);
// if offset equals -60 then the time zone offset is UTC+01

Converting date formats without timezone conversion?

I'm trying to do this without adding moment js to my project but it seems more difficult than I'd like.
if I get a date that's formatted as : "2021-07-19T12:15:00-07:00"
Is there an efficient way to have it formatted as:
"12:15 pm"
regardless of where me and my browser are located?
I've gotten as far as some other answers with no luck, for example:
var date = new Date('2021-07-19T12:15:00-07:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);
Thanks!
You could use Date.toLocaleTimeString() to format the time, this will give you the time in the local timezone, if we remove the UTC offset.
There are other options available here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
let timestampWithUTCOffset = "2021-07-19T12:15:00-07:00";
let timestampWithoutUTCOffset = timestampWithUTCOffset.substr(0,19);
console.log( { timestampWithUTCOffset , timestampWithoutUTCOffset });
let dt = new Date(timestampWithoutUTCOffset);
console.log('Time of day:', dt.toLocaleTimeString('en-US', { timeStyle: 'short' }))

Format Localized Iso date to hh:mm:ss

I am trying to convert a UTC date to local time on my node server and finally return the localized time in the format of hh:mm:ss (not using Moment JS). I'm passing in the timezone offset from the client to Node, which is GMT-6.
My original time is: 2017-05-05T00:25:11.378Z
// ISOTimeString = `2017-05-05T00:25:11.378Z`
// offsetInMinutes = 360; (GMT - 6)
function isoDateToLocalDate(ISOTimeString, offsetInMinutes) {
var newTime = new Date(ISOTimeString);
return new Date(newTime.getTime() - (offsetInMinutes * 60000));
}
The localized time is 2017-05-04T18:25:11.378Z, which is correct (2017-05-05T00:25:11 - 6 hours = 2017-05-04T18:25:11).
// localIsoDate: 2017-05-04T18:25:11.378Z Date object
function formatTime(localIsoDate) {
var hh = localIsoDate.getHours();
var mm = localIsoDate.getMinutes();
var ss = localIsoDate.getSeconds();
return [hh, mm, ss].join(':');
}
// formatted: 12:25:11
The problem is, while still on the server, when I try to format into hh:mm:ss, it subtracts another 6 hours, giving me 12:25:11. I don't want to convert again, I simply want to format and display 18:25:11 from the already localized time.
How can I do this?
Note: Keep in mind I do not have the option to convert timezones after it's passed back to the client in my case.
The isoDateToLocalDate seems to be OK, however in the formatTime you need to use UTC methods, otherwise you are getting the host local values, not the adjusted UTC values.
Also, in ISO 8601 terms (and general convention outside computer programming), an offset of 360 represents a timezone of +0600, not -0600. See note below.
// ISOTimeString = 2017-05-05T00:25:11.378Z
// ECMAScript offsetInMinutes = 360; (GMT-0600)
function isoDateToLocalDate(ISOTimeString, offsetInMinutes) {
var newTime = new Date(ISOTimeString);
return new Date(newTime.getTime() - (offsetInMinutes * 60000));
}
// localIsoDate: 2017-05-04T18:25:11.378Z Date object
function formatTime(localIsoDate) {
function z(n){return (n<10?'0':'')+n}
var hh = localIsoDate.getUTCHours();
var mm = localIsoDate.getUTCMinutes();
var ss = localIsoDate.getUTCSeconds();
return z(hh)+':'+z(mm)+':'+z(ss);
}
var timeString = '2017-05-05T00:25:11.378Z';
var offset = 360;
console.log(formatTime(isoDateToLocalDate(timeString, offset)))
ECMAScript timezone signs are the reverse of the usual convention. If the client timezone offset is +0600 then their host will show -360.

Date calculation - Daylight saving time (DST) and Timezone issue - Turkey

Date calculation issue in JavaScript on Browser. There are 3 parameters -
From Date, No. of days & To Date
From Date selected using calendar component in JavaScript = 30/10/2016
No. of days entered = 2
Based on no. of days entered "To Date" should be calculated, so as per above input of From date & No. of days calculated "To Date" value should be 01/11/2016 but due to some wrong calculation it's showing 31/10/2016.
Time Zone - Istanbul, Turkey
Please refer below image for code snipped -
As it is clear from code snipped that prototype JavaScript library being used.
dateUtil.prototype.addDays=function(date,noofDays)
{
var _dateData=date.split("/");
var _date=eval(_dateData[0]);
var _month=eval(_dateData[1]);
var _year=eval(_dateData[2]);
var newFormatedDate = new Date(""+_month+"/"+_date+"/"+_year);
var newAddedDate=newFormatedDate.getTime() + noofDays*24*60*60*1000;
var theDate = new Date(newAddedDate);
var dd = theDate.getDate();
var mm = theDate.getMonth()+1; // 0 based
if(mm<10)
mm="0"+mm;
var yy = theDate.getYear();
if (yy < 1000)
yy +=1900; // Y2K fix
var addedDate=""+dd+"/"+mm+"/"+yy;
return addedDate;
}
It seems noofDays*24*60*60*1000 logic is problem where DST is not being considered.
There are 2 timezone showing with the same code but with different date format.
Please could you advise any guidance or read-up on this.
Edit :
JavaScript code added.
Probably not worth posting the code since it has some fundamental errors that should not have survived the new millennium.
var _date = eval(_dateDate[0]);
Don't use eval. There are a small number of cases where it is appropriate, but in general, just don't use it. Ever. The above is the same as:
var _date = _dateDate[0];
Then there is:
var newFormatedDate = new Date('' + _month + '/' + _date + '/' + _year)
You started on the right track by avoiding parsing strings with the Date constructor by splitting the date string into it's parts. But then you undid that good work by creating a new string and parsing it with Date. Just use parts directly:
var newFormatedDate = new Date(_year, _month-1, _date)
which removes all the vagaries of Date parsing and is less to type as well. Also, Date objects don't have a format, so a name like date is fine.
To add n days, just add them to the date:
var date = new Date(_year, _month-1, _date)
date.setDate(date.getDate() + 2);
So your function can be:
function dateUtil(){}
/* Add days to a date
** #param {string} date - date string in dd/mm/yyyy format
** #param {number} noofDays - number of days to add
** #returns {Date}
*/
dateUtil.prototype.addDays = function(date, noofDays) {
var dateData = date.split('/');
var date = new Date(dateData[2], dateData[1] - 1, dateData[0]);
date.setDate(date.getDate() + +noofDays);
return date;
}
var d = new dateUtil();
console.log(d.addDays('23/09/2016',3).toLocaleString());
I've use +noofDays to ensure it's a number. Also, the SO console seems to always write dates as ISO 8601 strings in Z time zone so I've used toLocaleString to keep it in the host time zone.

Compare javascript dates without timezone

I'm doing something that should be really simple: I'm getting a string that represents an expiration date and using JavaScript to determine whether or not the expiration date has come to pass. My approach has been as follows:
var dateStringFromJson = "2015-09-11T11:21:48.113";
var expirationDate = new Date(Date.parse(dateStringFromJson));
if (expirationDate > new Date()) {
// Expiration not up
}
If I executed this function at a time before the expiration, say 10:50am, the comparison would fail and the function would act as if the expiration date was up.
I'm confident this problem has to do with JavaScript's timezone conversion. I'm in UTC-7 but my customers may be in any time zone across the U.S., so timezone specific fixes will not work here. I'd also prefer not to add an external library like moment.js to the project unless absolutely necessary.
Use a function to localize the json string. When you parse a date string without a time zone, it assumes it is in UTC. See my answer to a similar question for an explanation of how the localizeDateStr() function works.
function localizeDateStr(date_to_convert_str) {
var date_to_convert = new Date(date_to_convert_str);
var local_date = new Date();
date_to_convert.setHours(date_to_convert.getHours() + (local_date.getTimezoneOffset() / 60));
return date_to_convert;
}
function checkExpired() {
var dateString = document.getElementById('date').value;
var expirationDate = localizeDateStr(dateString);
if (expirationDate > new Date()) {
alert("Expiration not up.");
} else {
alert("Expired!");
}
}
Expiration Datetime:
<input id="date" type="text" value="2015-09-11T11:21:48.113" />
<button id="btn" onclick="checkExpired()">Is expired?</button>
You can parse the date manually if its format is consistent:
var DATE_STRING = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})$/;
var match = DATE_STRING.exec(dateStringFromJson);
var expirationDate = new Date();
expirationDate.setFullYear(+match[1]);
expirationDate.setMonth(+match[2] - 1);
expirationDate.setDate(+match[3]);
expirationDate.setHours(+match[4]);
expirationDate.setMinutes(+match[5]);
expirationDate.setSeconds(+match[6]);
expirationDate.setMilliseconds(+match[7]);
Consider just putting the timestamp in UTC, though, which is how it’s parsed. (And add a Z to the end to indicate that.)

Categories