I am using moment-timezone library to build a UI that needs to be relative to a variety of timezones.
I am taking an input of a timezone, i.e "America/Chicago" and need to get the start of day in GMT.
For instance, if today is March 27th at 9am Chicago time (2pm GMT), I need to get the date in epoch seconds for March 27th, 00:00 AM.
I'm using the moment.tz("America/Chicago").startOf('day') but I keep getting Tue Mar 27 2018 01:00:00 GMT-0400 (EDT) . Any idea how to do this?
Thanks
// This part you are already doing correctly.
// You get back a Moment object representing the start of the current day in Chicago:
var m = moment.tz("America/Chicago").startOf('day');
I need to get the date in epoch seconds
// Ok, so simply now get the associated Unix Time
var timestamp = m.unix();
Also note that the correct terminology is "Unix Time", not "epoch seconds".
See my blog post: "Please don't call it Epoch Time".
... but I keep getting Tue Mar 27 2018 01:00:00 GMT-0400 (EDT)
You are probably either looking at _d or a Date object, or rather the string representation of one. Don't. See this Moment.js documentation for details.
Per your comment:
I need to take the current time in a specific timezone. I then need to convert that time to the corresponding day in GMT. Finally I need to get the midnight epoch timestamp of that GMT day.
That's a little different then you originally asked, but it would be like this:
var timestamp = moment.utc().startOf('day').unix();
Note that there's no purpose in involving another time zone for this operation. Logically, when asking for "Now in time zone A converted to time zone B", it's the same as asking for "Now in time zone B". In other words, you would get the same value even when the time zone was present:
var timestamp = moment.tz('America/Chicago').utc().startOf('day').unix();
So you're better off just leaving the time zone out.
Related
I'm trying to understand ISO8601 time format
What does this value mean?
2019-11-14T00:55:31.820Z
I understand this as such
2019-11-14 // November 14th, 2019
T00:55:31 // 12:55 AM in GMT time (London)
.820 // why is this needed or specified?
Z // The "Z" indicates to store this as GMT time (London)
I don't understand why the .820 is needed here. Reading into it, this refers to timezone 820, which is California.
If I were to go to the Javascript console and write this with and without that 820 value, I would get the same results, based on my locale (EST time zone)
new Date('2019-11-14T00:55:31.820Z') // Wed Nov 13 2019 19:55:31 GMT-0500 (Eastern Standard Time)
new Date('2019-11-14T00:55:31Z') // Wed Nov 13 2019 19:55:31 GMT-0500 (Eastern Standard Time)
What does the prefix value before the Z actually do?
The "Z" indicates to store this as GMT time (London)
No, it indicates that the time value presented is in UTC, not that you should store it in GMT/UTC. It tells you what time zone to interpret the information provided in.
I don't understand why the .820 is needed here. Reading into it, this refers to timezone 820, which is California.
That's milliseconds, not a time zone. It's 820ms into 00:55:31 (e.g., it's 180ms away from being 00:55:32).
If I were to go to the Javascript console and write this with and without that 820 value, I would get the same results, based on my locale (EST time zone)
Only because the output of whatever console you're quoting doesn't include milliseconds. If you check the actual dates, you'll see that they're 820ms apart:
const dt1 = new Date('2019-11-14T00:55:31.820Z');
const dt2 = new Date('2019-11-14T00:55:31Z');
console.log(dt1.valueOf() - dt2.valueOf()); // 820
(The underlying value of a Date instance is the number of milliseconds it represents since Jan 1st 1970 at midnight UTC. So if we subtract d2 [which doesn't have the .820] from d1 [which does], we see they're 820ms apart.)
I have a situation where I am always returned the date from the server as a UK date time string.
E.g. '2020-07-19 16:40:00'
This would be 4:40PM in UK at +01:00, or 3:40PM UTC.
I want to be able to convert this time from GMT to the local time on the computer;
If I do this when in the UK...
var date = new Date('2020-06-19 16:40:00 GMT');
it returns Fri Jun 19 2020 17:40:00 GMT+0100 (British Summer Time)
Which is an hour out.
If I do the date in winter time (without daylight savings), this is correct.
var date = new Date('2020-01-19 16:40:00 GMT');
returns Sun Jan 19 2020 16:40:00 GMT+0000 (Greenwich Mean Time)
Is there a way I can correctly adjust this to always give the correct time regardless of what timezone the computer is set in, based on UK clock times.
Thanks in advance
As I understand your question, you don't know if the timestamp from the server is GMT or BST as the offset isn't included. You can work it out using plain JS but it's somewhat kludgy and error prone, see Calculate Timezone offset only for one particular timezone.
It would be much better to get the server to use an ISO 8601 format supported by ECMAScript and either send the offset or always use UTC/GMT.
If that isn't an option, you can use a library like Luxon to specify the location (and hence offset rules) to use for parsing, e.g.
let DateTime = luxon.DateTime;
['2020-07-19 16:40:00', // BST +1
'2020-01-19 16:40:00' // GMT +0
].forEach(ts => console.log(
DateTime.fromFormat(ts, 'yyyy-LL-dd HH:mm:ss', {zone: 'Europe/London'}))
);
<script src="https://cdn.jsdelivr.net/npm/luxon#1.24.1/build/global/luxon.min.js"></script>
PS Don't forget to always tell the parser the format to parse.
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>
Consider the following date object which is created in JavaScript.
var date = new Date("2017-09-07T16:46:06.000Z");
This date object should be equivalent to Sep 7 2017 4:46:06 PM
However, in the browser console, when I type the following:
console.log(date);
The following is returned:
Fri Sep 08 2017 02:46:06 GMT+1000 (E. Australia Standard Time)
The time is wrong. (It actually is today's date, but the time is completely wrong).
Key points of confusion:
My computer timezone is set to GMT+1000 (Australia/Brisbane)
When I created the date object, I did not specify the timezone, therefore it should conform to my systems timezone
When I log the date object to the console, it is still using GMT+1000 (Australia/Brisbane) but the date is different
When you created the date, you did specify a timezone. That Z at the end means Zulu or Greenwich Mean Time. Your computer is 10 hours off from GMT, so it adjusts to your local timezone for display.
If you want the date to be in your local time zone, remove the Z
var date = new Date("2017-09-07T16:46:06.000Z");
So it looks like the Z at the end of your date string is meant to represent UTC or Zulu time
var date = new Date("2017-09-07T16:46:06.000");
should be the correct solution
This question already has an answer here:
HTML Input type datetime-local setting the wrong time-zone
(1 answer)
Closed 7 years ago.
I'm writing a MVC 5 web application. Into this, I have multiple lists that I propagate and manage through javascript and jquery (one dataset, dependent select controls, and adding ajax callbacks would complicate it unnecessarily.)
The issue I have is: I have a hidden for field formatted to ISO 8601. I run into issues when I display the date in the user's local time, I get a shifted date.
So if the date were stated as: 01-01-2009 (in iso 8601 format: 2009-01-01), the user sees: 12-31-2008.
When I parse the date I'm using:
this.date = new Date(Date.parse(originalString));
/* ^- Date.parse is giving me a number. */
To display the text of the date I am using:
admin.date.toLocaleDateString().Concat(...
Do I need to do any sort of patch-up to adjust things to the proper time-zone? The date, when using console.log(admin.date); shows the original 2009-01-01
I'm thinking there's some parameter I'm not specifying correctly in the toLocaleDateString, but my familiarity level with it is low.
Edit: The goal is to prevent the date shift. All we store is the date, the time aspect is dropped. We have multiple time-zones posting to this database, and the goal is: We use the date of the person who posted it, time dropped. Were the date May 01, 2015, I want anyone who sees that date to see May 01, 2015, the 'toLocaleDateString' is merely a means to get it to appear format correct for their region. So someone who views dates as yyyy-mm-dd will see it properly.
Based on the documentation for Date.parse:
The Date.parse() method parses a string representation of a date, and returns the number of milliseconds since January 1, 1970, 00:00:00 UTC.
You are getting back the epoch time in UTC for your parsed date string hence why the date is off for local times. So, you would need to know the time difference between the local time and UTC which Date.getTimezoneOffset provides (in minutes) in order to set the correct date for the local time:
> var date = new Date(Date.parse('2009-01-01'));
undefined
> date;
Wed Dec 31 2008 19:00:00 GMT-0500 (EST)
> date.getTimezoneOffset();
300
> date.setMinutes(date.getTimezoneOffset());
1230786000000
> date;
Thu Jan 01 2009 00:00:00 GMT-0500 (EST)
One thing to note though is:
...the offset is positive if the local timezone is behind UTC and negative if it is ahead.
So you might need to take care for locales where the value is negative if this applies to your application. If so maybe just omitting negative values would be enough since the date should be the same if a locale's timezone is ahead of midnight UTC.
EDIT: To compensate for possible issues with daylight savings time:
> var dateVals = String.prototype.split.call('2009-01-01', '-');
undefined
> var date = new Date(dateVals[0], dateVals[1] - 1, dateVals[2]);
undefined
> date
Thu Jan 01 2009 00:00:00 GMT-0500 (EST)