My scenario is this:
I have a datepicker that accepts input from the user and it assumes the date/time picked is local time. I can't seem to change this behavior. The user should actually be picking the date/time in Europe/London time as they are booking a service in London at that time.
Lets say they are booking a flight from London at 5AM.
So I have this date the user picked (from New Zealand):
2019-08-01T05:00:00+12:00 (NZ time)
I need to change this to:
2019-08-01T05:00:00+01:00 (Europe/London time)
After that I am sending to server and storing as UTC.
I am using momentjs if that helps.
Edit: Latest attempt: I just need to figure out how to get the timezone offset from the exact time the user entered so I have daylight savings covered. e.g. below I am getting the UK offset for the day before so may have DST issues
const moment = require('moment-timezone');
const nzd = '2019-08-01T05:00:00+12:00'; // This is the date my user entered via the datepicker
const ukTempString = moment(new Date(nzd.slice(0, -6))).tz('Europe/London').format('YYYY-MM-DDTHH:mm:ssZ'); // 2019-07-31T18:00:00+01:00
const ukOffset = ukTempString.substr(ukTempString.length - 6); // +01:00
const ukString = nzd.slice(0, -6) + ukOffset; // 2019-08-01T05:00:00+01:00
const ukDate = new Date(ukString); // I can then this to the backend
Edit:
Current solution:
No DST in UK example:
let nzd = moment('2019-10-27T05:00:00+13:00'); // This is the date my user entered via the datepicker
let nzString = nzd.format('YYYY-MM-DDTHH:mm:ssZ');
let ukd = moment().tz('Europe/London');
ukd.set(nzd.toObject());
console.log(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // 2019-10-27T05:00:00+00:00
let ukDate = new Date(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // I can then this to the backend
console.log(ukDate.toUTCString()); // Sun, 27 Oct 2019 05:00:00 GMT
Has DST in UK example (same code):
nzd = moment('2019-10-27T00:30:00+13:00'); // This is the date my user entered via the datepicker
nzString = nzd.format('YYYY-MM-DDTHH:mm:ssZ');
ukd = moment().tz('Europe/London');
ukd.set(nzd.toObject());
console.log(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // 2019-10-27T00:30:00+01:00
ukDate = new Date(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // I can then this to the backend
console.log(ukDate.toUTCString()); // Sat, 26 Oct 2019 23:30:00 GMT
My scenario is this:
I have a datepicker that accepts input from the user and it assumes the date/time picked is local time. I can't seem to change this behavior. The user should actually be picking the date/time in Europe/London time as they are booking a service in London at that time.
Lets say they are booking a flight from London at 5AM.
So I have this date the user picked (from New Zealand):
2019-08-01T05:00:00+12:00 (NZ time)
I need to change this to:
2019-08-01T05:00:00+01:00 (Europe/London time)
After that I am sending to server and storing as UTC.
I am using momentjs if that helps.
Edit: Latest attempt: I just need to figure out how to get the timezone offset from the exact time the user entered so I have daylight savings covered. e.g. below I am getting the UK offset for the day before so may have DST issues
const moment = require('moment-timezone');
const nzd = '2019-08-01T05:00:00+12:00'; // This is the date my user entered via the datepicker
const ukTempString = moment(new Date(nzd.slice(0, -6))).tz('Europe/London').format('YYYY-MM-DDTHH:mm:ssZ'); // 2019-07-31T18:00:00+01:00
const ukOffset = ukTempString.substr(ukTempString.length - 6); // +01:00
const ukString = nzd.slice(0, -6) + ukOffset; // 2019-08-01T05:00:00+01:00
const ukDate = new Date(ukString); // I can then this to the backend
Edit:
Current solution:
No DST in UK example:
let nzd = moment('2019-10-27T05:00:00+13:00'); // This is the date my user entered via the datepicker
let nzString = nzd.format('YYYY-MM-DDTHH:mm:ssZ');
let ukd = moment().tz('Europe/London');
ukd.set(nzd.toObject());
console.log(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // 2019-10-27T05:00:00+00:00
let ukDate = new Date(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // I can then this to the backend
console.log(ukDate.toUTCString()); // Sun, 27 Oct 2019 05:00:00 GMT
Has DST in UK example (same code):
nzd = moment('2019-10-27T00:30:00+13:00'); // This is the date my user entered via the datepicker
nzString = nzd.format('YYYY-MM-DDTHH:mm:ssZ');
ukd = moment().tz('Europe/London');
ukd.set(nzd.toObject());
console.log(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // 2019-10-27T00:30:00+01:00
ukDate = new Date(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // I can then this to the backend
console.log(ukDate.toUTCString()); // Sat, 26 Oct 2019 23:30:00 GMT
Share
Improve this question
edited Jul 28, 2019 at 20:25
MadMac
asked Jul 27, 2019 at 23:35
MadMacMadMac
5,0338 gold badges44 silver badges86 bronze badges
1
-
Once you have a JavaScript Date object like
date = new Date()
, since London is the location of UTC, you can get conveniently London-specific values (not accounting for daylight savings time) with eitherdate.getTime
(for the timestamp) or any of thedate.getUTC{{X}}
methods (e.g.date.getUTCHours
). See: developer.mozilla/en-US/docs/Web/JavaScript/Reference/… (If you need the DST-adjusted London time, that's technically not UTC anymore and you'd need to check whether DST is currently active in London.) – Cat Commented Jul 28, 2019 at 0:01
3 Answers
Reset to default 4Here is a simpler solution:
moment("2019-08-01T05:00:00+12:00")
.parseZone()
.tz("Europe/London", true)
.toISOString(true) // => "2019-08-01T05:00:00.000+01:00"
To explain that a bit:
- We parse the string, which interprets the string as being in NZ, but translates it to a local time, which may or may not be +12, depending on where your puter is
- use
parseZone
to undo that conversion, so that our date thinks of itself as being in +12, per the original string - Convert the time to London time using
tz
, but with the a second argument (calledkeepTime
) oftrue
, which means "instead of keeping the time the same and changing the local time, change what time it is to keep the local time the same". - Format the result in ISO, but pass a second argument (called
keepOffset
) telling it not to convert to UTC before display
So, that works, but perhaps it would be better to change the timepicker to London time so that the times they pick are already in the zone you want?
Edit, the equivalent Luxon code is a little more legible, if that helps explain it:
DateTime.fromISO("2019-08-01T05:00:00+12:00", { setZone: true })
.setZone("Europe/London", { keepLocalTime: true} )
.toISO()
- If you are not doing any date time conversion (like in your example), and just changing the time zone offset in the end of the string, just do a string operation, like this:
var nzd = '2019-08-01T05:00:00+12:00'
var ukd = nzd.slice(0, -6) + '+01:00'
console.log(ukd) // outputs 2019-08-01T05:00:00+01:00
- If you need to convert the full date and time, as you are using momentjs, you could use moment-timezone instead: https://momentjs./timezone/ . Then the following code do the trick:
const moment = require('moment-timezone')
var nz = moment('2019-08-01T05:00:00+12:00')
var uk = nz.tz('Europe/London').format()
console.log(uk) // outputs 2019-07-31T18:00:00+01:00
- If you want to get the time zone offset string, also use moment-timezone:
let ukd = "2019-10-27T01:59:00".split('T')
let finalDate = moment.tz(ukd[0] + "T" + ukd[1], "YYYY-MM-DDTHH:mm:ss", true, "Europe/London").tz('Europe/London').format('Z');
console.log(finalDate) // last minute still in DST, outputs +01:00
ukd = "2019-10-27T02:01:00".split('T')
finalDate = moment.tz(ukd[0] + "T" + ukd[1], "YYYY-MM-DDTHH:mm:ss", true, "Europe/London").tz('Europe/London').format('Z');
console.log(finalDate) // first minute after DST, outputs +00:00
This seems hacky and not clean code, but it's due to a bug in timezone that parses as UTC date instead of timezone date.
How about creating new Date
with timezone set explicite as UTC, but with values passed directly from the original Date
, like this:
function changeTimezoneToUtc(date: Date): Date {
return new Date(Date.UTC(date.getFullYear(), date.getMonth(),
date.getDate(), date.getHours(),
date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
}
Above is in typescript, but types can be ommited of course.