This question already has answers here:
How to initialize a JavaScript Date to a particular time zone
(20 answers)
Use JavaScript to convert a date string with timezone to a date object in local time
(3 answers)
Convert normal date to unix timestamp
(12 answers)
Closed 16 days ago.
This post was edited and submitted for review 14 days ago.
Not sure if anyone has asked about this before. I basically want to, using JavaScript, parse a datetime string, e.g.
"2023-03-12 01:30:56"
and turn it into a Unix timestamp.
I know parsing datetime can be a trivial task in JavaScript. However, I want to do it timezone-sensitive. I am working with mainly UK datetimes here, so we can assume all the given datetimes as UK times here. But the real problem here is that UK has two time zones - GMT and BST.
Instead of reinventing the wheel and write everything from scratch, I wonder if there are any existing function I can use to determine which time zone to use so that the datetime string can be converted into the correct Unix timestamp.
Note: I understand there might be some overlapping issues when the clock changes, but let's just assume the 'first parsed moment' is chosen to be output.
Add-on: Some of you may not have read my question clearly. Just want to emphasize the point of the question: The given datetime string has NO TIMEZONE given. I need a function to recognise the correct timezone depending on the date/time!
Here is the "rule" for changing between GMT(+00:00) and BST(+01:00) in the UK:
When does British Summer Time start?
BST starts when the clocks go forward in spring.
At 1am on the last Sunday in March, clocks 'spring forward' by one hour.
When does British Summer Time end?
BST ends when the clocks go back in autumn. At 2am on the last Sunday in October, the clocks 'fall back' by an hour.
Add-on 2: So in simple words, the given datetime string should be parsed as the time is in +01:00 timezone during summer, and in +00:00 during winter.
Add-on 3: Let me give an example: If the string given is "2023-02-04 01:30:00", then it should be parsed as if it is "2023-02-04T01:30:00.000+00:00" because it is in the winter time. If the string given is "2023-07-14 13:30:00", then it should be parsed as if it is "2023-07-14T13:30:00.000+01:00" because it is in the summer time.
Edit: I am sorry that this question has been voted to close, as none of the suggestions are relevant to the main point of my question.
Solution: I am posting below a not-so-elegant solution in case if anyone later wants to know about the solution to this user-oriented problem.
function parseUKDatetime(str) {
// str format: YYYY-MM-DD HH:MM:SS
var matches = str.match(/^\D*(\d\d\d\d)\D+(\d?\d)\D+(\d?\d)(?:\D+(\d\d)\D+(\d\d)\D+(\d\d))?\D*$/);
if (matches) {
var utcDatetimeStr = matches[1]+'-'+('00'+matches[2]).slice(-2)+'-'+('00'+matches[3]).slice(-2)+'T'+(typeof matches[4]=='undefined'?'00:00:00':(matches[4]+':'+matches[5]+':'+matches[6]))+'+0000';
var parsedDate = new Date(utcDatetimeStr);
var unixTime = parsedDate.getTime();
if (isNaN(unixTime)) {
return null;
}
var d1 = new Date(matches[1], 3, 0);
d1.setDate(d1.getDate() - d1.getDay());
d1 = d1.getTime() + 7200000;
var d2 = new Date(matches[1], 10, 0);
d2.setDate(d2.getDate() - d2.getDay());
d2 = d2.getTime() + 10800000;
if (d1 <= unixTime && d2 > unixTime) {
unixTime -= 3600000
}
return unixTime;
}
return null;
}
To people who are going to comment further about the lack of timezone: - That IS the point of my question. I want the function to work out the timezone when user only provides the date and time. Please stop providing suggestions/answers that force me to provide the timezone.
Some of you have not understood my question clear enough before voting to close my post... :-( I am not asking the kind of general questions you have on your mind when you only pick up the keywords "date parsing" and "timezone".
Related
This question already has answers here:
How to create time in a specific time zone with moment.js
(5 answers)
Closed 2 years ago.
Small problem that's driving me nuts. I'm getting a time as a string from an API call, and I'm getting the timezone the time is in, as two separate strings. I'm trying to create a moment that is using this given data and it's taking my local machine timezone as a starting point and adjusting into the given zone
let timeFromApi = "01 Jan 2021 15:00"; //That's 3pm, Eastern Standard Time
let timeZoneFromApi = "America/Indianapolis"; //Server says "time I gave is in EST"
If I do either of these, with my local machine set to UTC:
let x = moment.tz(timeFromApi, timeZoneFromApi).format("YYYY-MM-DDTHH:mm:ss zz");
let y = moment(timeFromApi).tz(timeZoneFromApi).format("YYYY-MM-DDTHH:mm:ss zz");
Then they both end up containing "2021-01-01 10:00 -05"..
Moment seems to assume the given string is in timezone the local machine is in: If I set the local machine to EST, then I get "2021-01-01 15:00 -05" like I expect...
... but I don't want moment reading the local machine time at all. I literally want to give it a time, and give it a timezone and have it create that time in that timezone - how do I do this?
Having gone through the same sort of trouble, I can tell you that
let x = moment.tz(timeFromApi, timeZoneFromApi);
is the correct method. The documentation also says that is the way to do. I suspect your trouble is the formatting not the parsing. The z and zz formatting options are deprecated as of 1.6 (see https://momentjs.com/docs/#/displaying/). So I'd play with the formatting a bit.
This question already has answers here:
JavaScript function to add X months to a date
(24 answers)
Adding months to a Date in JavaScript [duplicate]
(2 answers)
Closed 2 years ago.
I'm trying to find a method that reliably subtracts 1 month from a javascript date object.
I have this code:
var shippedDate = new Date('12/31/2020');
var tempDate = new Date(shippedDate.setMonth(shippedDate.getMonth() - 1)); //subtract 1 month
alert(tempDate);
The value in tempDate after this code runs is 12/1/2020 when it should actually be 11/30/2020.
I checked my math with this online date calculator: https://www.timeanddate.com/date/dateadded.html?m1=12&d1=31&y1=2020&type=sub&ay=&am=1&aw=&ad=&rec=
Thanks.
December has 31 days so when you subtract 1 month, you get 31 November which doesn't exist, so it rolls over to 1 December.
You can test the date (day in month) to see if it's the same, and if not, set the date to 0 so it goes to the last day of the previous month.
Also, setDate modifies the Date object so no need to create a new one:
function subtractMonth(date, months) {
let d = date.getDate();
date.setMonth(date.getMonth() - months);
if (date.getDate() != d) {
date.setDate(0);
}
return date;
}
let d = new Date(2020, 11, 31); // 31 Dec 2020
console.log(subtractMonth(d, 1).toString()); // 30 Nov 2020
This has side effects so that sequentially subtracting 2 months may give a different result to subtracting 2 months in one go.
Also in regard to new Date('12/31/2020'), see see Why does Date.parse give incorrect results?
PS
I answered this before I remembered that there were plenty of questions about adding months that also cover subtracting. So I marked this question as a duplicate and rather than delete this answer, left it for posterity.
If you wish to vote for an answer, please go to one of the duplicates and vote for an answer there. :-)
On my own experience, I may qualify all around Date calculation in javascript as completely unbearable pain.
Avoid as possible own crafted function to any Date manipulation. There are too many traits to lose mind at all. Timezones, wrong clocks, timezone on your own host vs. timezone on server, unexpected toString conversion according to local host timezone/clock.
If you rally need to make some dates calculation use battle tested library, like date-fns, moment.js, etc.
By the way your example almost correct, you just have chosen not suitable time to try to test it. The only one that I see problematic it's using setMonth that mutate original shippedDate.
This question already has an answer here:
Why is new Date() removing a day? - Javascript [duplicate]
(1 answer)
Closed 6 years ago.
This is the first time that I get this result.
I'm using a Telerik control RadDatePicker and I'm assigning the date client-side.
The thing is that the control doesn't accept a string as date, but a Date object in javascript
So, my code to set the date in the control is
var radDateControl = $find("radDateControl");
radDateControl.set_selectedDate(new Date('2016-04-26'));
But, I realized that the new Date is returning the date as yesterday! Why?
It's 5:58pm Eastern Time (US & Canada) right now. And if I do this
alert(new Date('2016-04-26'));
I get this
Mon Apr 25 2016 20:00:00 GMT-0400 (Eastern Daylight Time)
Why and how can I get the day as of today.
Update
What I finally did it was this. Hope it can help others.
var dateAsString = "2016-04-26";
var year = dateAsString.split('-')[0];
var month = dateAsString.split('-')[1];
var day = dateAsString.split('-')[2];
var date = new Date(Date.UTC(year, month - 1, day, 0,0,0));
date.setTime(date.getTime() + date.getTimezoneOffset() * 60 * 1000);
rpdDateControl.set_selectedDate(date);
The newly created date object is totally correct. The wrong part in here or at least the part confusing you is your browser, parsing the date object into your current timezone.
If you create a new date object and save it into a variable ...
var date = new Date('2016-04-26');
... you will get what you've asked for. A Date object representing the 26/04/2016 (in UTC).
Since you use your browser to get your date objects value, the value just gets parsed through your local timezone (in your case Eastern Daylight Time). So if you want to handle the correct date which you've used to create the new date object, you may use .toUTCString().
I know, parsing timezones can be really frustrating. In order to handle different timezones, you may try out Moment or Moment Timezone. I guess moment should fit your needs, but just for the completion.
Just use Date.now() instead. I'm not sure why the string isn't working but this will work anyways.
You are asking date 26, but with timezone changes it gives you back 2 hours, why not just alert(new Date()); and let it give you its current date?, also to check it go to the server using ssh and type date, if its not the date you are you can use tzselect to modify the server to your date
I use moment.js to display a UTC date in the users local timezone:
var date = new Date(Date.UTC(2016,03,30,0,0,0));
var now = new Date();
var diff = (date.getTime()/1000) - (now.getTime()/1000);
var textnode = document.createTextNode(moment(date).format('dddd, DD.MM.YYYY') + ' a las ' + moment(date).format('HH:mm A'));
document.getElementsByClassName("date")[0].appendChild(textnode.cloneNode(true));
I later use the diff variable to show a countdown timer.
I would like to show a different countdown timer to everyone in their local time zone. (Using the difference till its midnight in their time zone, not in UTC)
But I am struggeling to get it work. Instead of using var date = new Date(Date.UTC(2016,03,30,0,0,0)); I probably need to use some function of moment.js that gives me till midnight in the users time zone.
The best example would be new years eve. If I use UTC everyone would have the same counter (9 hours left) but in different parts of the world this wouldn't make sense. For someone in australia it should be 2 hours left, and for someone in the US 14 hours.
I'm not sure that I fully understand your question, but I'll give you some general advice and tips.
When using moment.js, there is very little need to ever use the Date object. Only use it for interacting with other APIs that expect a Date object.
To get a moment in UTC, just use moment.utc(...), passing the appropriate arguments, such as moment.utc([2016,3,30]) or moment.utc('2016-04-30') for midnight April 30th UTC.
If you want to convert that back to the user's local time, use the .local() function. For example, moment.utc('2016-04-30').local() will create a moment with the equivalent local time to the UTC time provided.
If you want a moment in the user's local time, then that would be moment(...), such as moment([2016,3,30]) or moment('2016-04-30') for midnight April 30th local time.
You can difference two moments using the diff function, which can give the answer in specific units, such as m1.diff(m2, 'seconds') where m1 and m2 are moment objects.
You don't need to call format twice. Just encapsulate any text you want outputed with square brackets. .format('dddd, DD.MM.YYYY [a las] HH:mm A')
You might look into moment's locale support. If I'm not mistaken, "a las" indicates Spanish, however it's not always "a las", but sometimes "a la", if the hour is 1. Also, moment only uses those words in its .calendar() function, such as when producing a phrase like "mañana a las 13:17". A regular date formatted with .format('LLLL') in the Spanish locale would be something like: "sábado, 19 de marzo de 2016 13:17". So, you might want to verify that "a las" is exactly what you want in every case.
The title to this question was how to set a date to midnight. For that, I recommend using moment's startOf function. m.startOf('day') will give set the moment m to the start of the day, which is usually midnight. Keep in mind that not every local day actually starts at midnight in every time zone. Due to anomalies like daylight saving time, some days might start at 1:00. For example, this occurs in Brazil on October 16th this year.
Also, if you created the moment in UTC mode, you may wish to convert it back to local mode first before setting it to the start of the day. If you don't want to change the original moment object, be sure to clone it first.
Putting this all together:
var m1 = moment.utc([2016,3,30]);
var m2 = m1.clone().local().startOf('day');
var now = moment();
var diff = m1.diff(now, 'seconds');
Well I need to know what hours will be 9am in user time compared with my timezone.
like:
I'm from Brazil 9 am GMT -0300
i.e: some user from 'Cairo' access my website then I need to know when will be 9 am in his time compared with my time 'Cairo' gmt is +0200.
Is there a way to do it with Javascript?
You are probably looking for getTimezoneOffset() method
(see http://www.w3schools.com/jsref/jsref_gettimezoneoffset.asp):
var d = new Date()
var n = d.getTimezoneOffset();
n will be the timezone difference between UTC and Local Time in minutes.
More comprehensive guide here: http://www.onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/.
EDIT:
Oh, I forgot about the future time part. In that case, it should be enough to create custom date instance using one of the extended constructors:
var d = new Date(year, month, day, hours, minutes, seconds, milliseconds);
It can be used to determine the timezone difference at that time.
You can easily determine the offset o at some time, and the final offset at the specified time is either o, o + 60 or o - 60, which can be easily checked with getTimezoneOffset() on the Date object created with the extended constructor.
In the worst-case scenario, you might have to do 2-3 calculation steps to determine your final result.
Checkout: javascript timezone converter, there's an already open discussion there about your inquired topic.