Change timezone to another timezone - javascript

I have a form in which the user selects a date, time and a timezone.
Example:
let date = '02.09.2020';
let time = '16.00';
let timezone = '-07.00';
I want to convert this date with timezone : '+02.00';
I have a hidden text input in which i pass the actualized date format i want.
I don't want to use momment.js for such a small thing.

You could construct a UTC date with an offset of the given timezone -07.00. Then you can add the desired offset of +02.00 to that.
Update: I am going to assume the following, based on other user's input.
Local date: 2020-02-09 16.00 -07:00
UTC date: 2020-02-09 23:00 (subtract the local timezone offset)
UTC +2: 2020-02-10 01:00 (add the desired offset)
const offsetDate = (dateStr, timeStr, srcOffset, destOffset) => {
const tokenize = str => str.split('.').map(v => parseInt(v, 10));
const [ month, date, year ] = tokenize(dateStr);
const [ hour, minute ] = tokenize(timeStr);
const [ srcOffHours, srcOffMins ] = tokenize(srcOffset);
const [ destOffHours, destOffMins ] = tokenize(destOffset);
const utcDate = new Date(Date.UTC(year, month - 1, date, hour, minute));
const srcOff = srcOffHours * 36e5 + srcOffMins * 6e4;
const destOff = destOffHours * 36e5 + destOffMins * 6e4;
utcDate.setTime(utcDate.getTime() - srcOff + destOff);
console.log(`Time: ${utcDate.toISOString()}`);
return [
utcDate.getUTCDate(),
utcDate.getUTCMonth() + 1,
utcDate.getUTCFullYear().toString().substr(2)
].map(v => (v + '').padStart(2, '0')).join(':');
};
const date = '02.09.2020';
const time = '16.00';
const timezone = '-07.00';
console.log(offsetDate(date, time, timezone, '+02.00')); // 10:02:20

You can do something like this
let date = new Date();
let event = date.toLocaleString('ko-KR', { timeZone: 'UTC' })) // if the timezone was Korea

Related

Javascript get time in unix from a unix timestamp

How can I extract time only as a unix number from a unix timestamp?
For example:
const timeStamp = 1671682809 // Thursday, December 22, 2022 11:20:09 AM GMT+07:00
const unixTimeOnly = extractTime(timeStamp) // return a unix number that represents "11:20:09"
Thank you!
You could do this by subtracting the same date, with the clock set to midnight:
const timeStamp = 1671682809;
const date = new Date(timeStamp * 1000);
const midnightDate = new Date(date).setHours(0,0,0,0);
const justHMS = date - midnightDate;
// you may want to divide this number how you wish if you're not working in milliseconds
console.log(justHMS);

How can I store Hour and Minute in a universal time format?

I’m working on a website that teachers are entering their availability based on their local time zone
David from California is available Monday and Tuesday at 4 PM PST for example.
I want to show that availability to everyone else internationally in their local format
John from New York can see David is available at 7 PM EST
Is there standard way of doing this without storing local time zone in the db?
I was thinking just pick a random date (or even now) and stick the hour/minute to it, save it in UTC and to display it just ignore the date part. does that sound reasonable or there is a better way?
When storing local times, the related timezone data should be stored as well. The most portable identifiers at the moment are IANA representative locations like 'America/New_York'. That way changes to standard and daylight saving offsets are accommodated so that given a particular date, you can get details for one person's time and show it as a date and time for another person's location, adjusting for their offset on that date.
The following shows an algorithm, it uses a rough function from here, but I would strongly suggest using a library like Luxon instead, I just wanted to keep this plain JS.
The following gets a time and location for one user, then displays it as an equivalent time in the location of another user. Hopefully it's something along the lines of what you want to do.
// Function from https://stackoverflow.com/a/61364310/257182
/* #param {string} isoString - ISO 8601 timestamp without timezone
** e.g. YYYY-MM-DDTHH:mm:ss or YYYY-MM-DD HH:mm:ss
** #param {string} loc - IANA representateive location
** e.g. Europe/Berlin
** #param {boolean} returnOffset - if true, return the offset instead of timestamp
** #returns {string} if returnOffset is true, offset is ±HH:mm[:ss] (seconds only if not zero)
** if returnOffset is false, equivalent ISO 8601 UTC timestamp
*/
let getUTCTime = (function() {
let n = 'numeric';
let formatterOpts = {year:n, month:n, day:n, hour:n, minute:n, second:n, hour12: false};
function parse (isoString) {
let [Y,M,D,H,m,s] = isoString.split(/[\DT\s]/);
return new Date(Date.UTC(Y,M-1,D,H,m,s));
}
function toParts(date, formatter) {
return formatter.formatToParts(date).reduce((acc, part) => {
acc[part.type] = part.value;
return acc;
}, Object.create(null));
}
return function (isoString, loc, returnOffset = false) {
formatterOpts.timeZone = loc;
let formatter = new Intl.DateTimeFormat('en', formatterOpts);
let oDate = parse(isoString);
let utcDate = new Date(oDate);
let maxLoops = 3,
p, diff;
do {
p = toParts(utcDate, formatter);
diff = new Date(Date.UTC(p.year, p.month-1, p.day, p.hour, p.minute, p.second)) - oDate;
if (diff) {
utcDate.setTime(utcDate.getTime() - diff);
}
} while (diff && maxLoops--)
let dDiff = null;
if (maxLoops < 0) {
p = toParts(utcDate, formatter);
dDiff = Date.UTC(p.year, p.month - 1, p.day, p.hour, p.minute, p.second) - utcDate;
let msg = isoString + ' does not exist at ' + loc + ' due to ' +
'daylight saving change-over, shifting into DST';
}
let oDiff = dDiff || oDate - utcDate;
let sign = oDiff > 0? '+' : '-';
oDiff = Math.abs(oDiff);
let offH = oDiff / 3.6e6 | 0;
let offM = (oDiff % 3.6e6) / 6e4 | 0;
let offS = (oDiff % 6e4) / 1e3 | 0;
let z = n=>(n<10?'0':'')+n;
return returnOffset? `${sign}${z(offH)}:${z(offM)}${offS? ':' + z(offS) : ''}` :
utcDate.toISOString();
}
})();
// Given a local timestmap in format YYYY-MM-DDTHH:mm:ss and
// loc as IANA representative location
// Return equivalent ISO 8061 UTC timestmap
function getUTCString(timestamp, loc) {
return getUTCTime(timestamp, loc);
}
// Given a local timestmap in format YYYY-MM-DDTHH:mm:ss and
// loc as IANA representative location
// Return offset at loc as ±HH:mm[:ss]
// - seconds only included if not zero (typically pre-1900)
function getUTCOffset(timestamp, loc) {
return getUTCTime(timestamp, loc, true);
}
/* #param {string} person - name of person
** #param {string} date - date to get times in YYYY-MM-DD format
** #param {string} loc - IANA rep. loc. e.g. America/New_York
** #returns {string} timestamp for loc
*/
function showTimes(person, date, loc) {
// Get loc and time for person
let sourceLoc = data[person].loc;
let sourceTime = data[person].time;
// Get UTC date for time
let sourceDate = date + 'T' + sourceTime + ':00';
let sourceOffset = getUTCOffset(sourceDate, sourceLoc);
let utcDate = new Date(sourceDate + sourceOffset);
// Return local date for loc
return utcDate.toLocaleString('en-CA',{timeZone: loc, timeZoneName:'long', hour12: false});
}
let data = {
john: {
loc: 'America/Los_Angeles', // IANA representative location
time: '16:15' // Must be in HH:mm format
},
sally: {
loc: 'America/New_York',
time: '08:30'
}
}
let date = '2020-02-03';
let user1 = 'john';
let user2 = 'sally';
// Standard time
// Show John's time in Sally's location on Monday, 3 February 2020
console.log(
`${date} ${data[user1].time} for ${user1} in ${data[user1].loc } is\n\
${showTimes(user1,date, data[user2].loc)} for ${user2}`
);
// Daylight saving time
// Show Sally's time in John's location on Friday, 26 June 2020
date = '2020-06-26';
console.log(
`${date} ${data[user2].time} for ${user2} in ${data[user2].loc } is\n\
${showTimes(user2,date, data[user1].loc)} for ${user1}`
);
Here's an example similar to the above using Luxon:
let DateTime = luxon.DateTime;
let data = {
john: {
loc: 'America/Los_Angeles', // IANA representative location
startTime: '16:15' // Must be in HH:mm format
},
sally: {
loc: 'America/New_York',
startTime: '08:30'
}
}
console.log('----- Standard time -----');
// What is the date and time at Sally's location when John starts on
// on Monday, 3 February 2020?
let targetDate = '2020-02-03';
let johnStartString = targetDate + 'T' + data.john.startTime;
let johnStartDate = DateTime.fromISO(johnStartString, {zone: data.john.loc});
// ISO string for John's startTime
console.log('When John starts at : ' + johnStartDate.toISO());
// Create a date for Sally's loc based on John's
let sallyDate = johnStartDate.setZone(data.sally.loc);
console.log('For Sally it\'s : ' + sallyDate.toISO());
console.log('----- Daylight Saving time -----');
// What is the date and time at John's location when Sally starts on
// on Monday, 1 June 2020?
targetDate = '2020-06-01';
let sallyStartString = targetDate + 'T' + data.sally.startTime;
sallyStartDate = DateTime.fromISO(sallyStartString, {zone: data.sally.loc});
// ISO string for Sally's startTime
console.log('When Sally starts at: ' + sallyStartDate.toISO());
// Create a date for John's loc based on Sally's
let johnDate = sallyStartDate.setZone(data.john.loc);
console.log('For John it\'s : ' + johnDate.toISO());
<script src="https://cdn.jsdelivr.net/npm/luxon#1.23.0/build/global/luxon.min.js"></script>
I would store:
initial time of the day: int
end time of the day: int
original timezone: string
then, showing that to users is a UI problem.
you could calculate dynamically two dates (based on the stored times) in the original timezone and convert it to any target timezone on the fly.
an alternative is checking the time difference between original and target timezones (without calculating any date) and adding it to the initial/end times.. but I guess it's easier to go for the first option as the date classes have that kind of utils.
Keeping track of start and end hours can result in weird timezone errors.
For example, if someone selects Monday 6pm-9pm in EST, that's actually Monday 11pm - Tuesday 2am in UTC. That means the time range stored in UTC is Start: 11pm and End: 2am, which requires lots of code to work around these different scenarios.
A better idea may be to keep track of the starting hour and the number of hours until the ending time (elapsed time).

How can I find out if the current UTC time is at least 12 hours bigger than the given UTC time?

I want to find out if the current UTC time is at least 12 hours bigger than the given UTC time. The given UTC time always consists of UTCyear, UTCmonth, UTCdate, UTChour and UTCminute.
I have tried it with the code provided in the answer from the user Titulum, but it's not always working. For example, the code is not working in this case:
function isOlderThan12Hours(dateToCheck)
{
return Date.now() - dateToCheck > 43200;
}
const year = 2020;
const month = 3; // April
const date = 17;
const hour = 11;
const minute = 39;
const valuesAsDate = new Date(`${year}-${month+1}-${date}T${hour}:${minute}:00.000Z`);
In this case, valuesAsDate is "Invalid Date".
How can I find out if the current UTC time is at least 12 hours bigger than the given UTC time?
function isOlderThan12Hours(dateToCheck) {
return Date.now() - dateToCheck > 43200;
}
const year = 2019;
const month = 11; // December
const date = 31;
const hour = 16;
const minute = 40;
const valuesAsDate = new Date(year, month, date, hour, minute);
console.log(isOlderThan12Hours(valuesAsDate));

moment.js not factoring in the year when converting a date to Unix timestamp

I need to find the difference between 2 dates, 30/05/2019 and 30/04/2020. I am using this code:
var checkinTime = moment('30/05/2019', 'DD/MM/YYYY').unix();
var checkoutTime = moment('30/04/2020', 'DD/MM/YYYY').unix();
The 2019 value is correct, but the 2020 value is returning as if it is 2019. The values returned are '1590760800' and '1588168800' respectively. The first timestamp should be smaller than the second timestamp, but is bigger (by a month).
How do I get it to take future years into account?
Your code seems to be correct. I tried following code.
index.js
var moment = require('moment');
var checkinTime = moment('30/05/2019', 'DD/MM/YYYY').unix();
var checkoutTime = moment('30/04/2020', 'DD/MM/YYYY').unix();
console.log(' checkinTime: ' + checkinTime);
console.log('checkoutTime: ' + checkoutTime);
console.log(' diff dates: ' + (checkoutTime - checkinTime) / 86400);
checkinTime was smaller than checkoutTime and the date difference was 336 as below.
$ node index.js
checkinTime: 1559142000
checkoutTime: 1588172400
diff dates: 336
Here is an example in plain Javascript.
Notice that date objects in Javascript have a timestamps with a resolution of milliseconds, and Unix time is usually in seconds.
function parseDDMMYYY(input) {
const dateArrayText = input.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/);
if (!dateArrayText) return NaN;
// Decode dateArrayText to numeric values that can be used by the Date constructor.
const date = {
year : +dateArrayText[3],
month : (+dateArrayText[2]) - 1, // month is zero based in date object.
day : +dateArrayText[1]
}
const dateObject = new Date( date.year, date.month, date.day );
// Check validity of date. The date object will accept 2000-99-99 as input and
// adjust the date to 2008-07-08. To prevent that, and make sure the entered
// date is a valid date, I check if the entered date is the same as the parsed date.
if (
!dateObject
|| date.year !== dateObject.getFullYear()
|| date.month !== dateObject.getMonth()
|| date.day != dateObject.getDate()
) {
return NaN;
}
return dateObject;
}
const date1 = parseDDMMYYY('30/05/2019');
const date2 = parseDDMMYYY('30/04/2019');
const diffInMs = date2 - date1;
const diffInSeconds = Math.floor( (date2 - date1) / 1000 );
console.log( diffInMs );
console.log( diffInSeconds );

Converting a time string to a time value in javascript

I have a string that looks like "01:12:33" which is HH:MM:SS format. How can I convert that to a time value in JS?
I've tried the new Date() constructor and setting the year and day values to 0, then doing getTime(), but I am not having any lucky.
Prefix it with a date:
var hms = "01:12:33";
var target = new Date("1970-01-01T" + hms);
console.log(target);
There target.getTime() will give you the number of milliseconds since the start of the day;
Or, if you need it to be today's date:
var now = new Date();
var nowDateTime = now.toISOString();
var nowDate = nowDateTime.split('T')[0];
var hms = '01:12:33';
var target = new Date(nowDate + 'T' + hms);
console.log(target);
There target.getTime() will give you the number of milliseconds since the epoch.
You can add the following function that does the job for you :
function getDateFromHours(time) {
time = time.split(':');
let now = new Date();
return new Date(now.getFullYear(), now.getMonth(), now.getDate(), ...time);
}
console.log(getDateFromHours('01:12:33'));
To be able to do this, there should be a conversion of the string in HH:MM:SS format to JavaScript time.
Firstly, we can use Regular Expression (RegEx) to properly extract the values in that string.
let timeString = "01:12:33";
Extract values with RegEx
let regExTime = /([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])/;
let regExTimeArr = regExTime.exec(timeString); // ["01:12:33", "01", "12", "33", index: 0, input: "01:12:33", groups: undefined]
Convert HH, MM and SS to milliseconds
let timeHr = regExTimeArr[1] * 3600 * 1000;
let timeMin = regExTimeArr[2] * 60 * 1000;
let timeSec = regExTimeArr[3] * 1000;
let timeMs = timeHr + timeMin + timeSec; //4353000 -- this is the time in milliseconds.
In relation to another point in time, a reference time has to be given.
For instance,
let refTimeMs = 1577833200000 //Wed, 1st January 2020, 00:00:00;
The value above is is the number of milliseconds that has elapsed since the epoch time (Jan 1, 1970 00:00:00)
let time = new Date (refTimeMs + timeMs); //Wed Jan 01 2020 01:12:33 GMT+0100 (West Africa Standard Time)

Categories