javascript getMonth() off by 2? - javascript

I understand that getMonth() is zero indexed so, for example, June is 5. But I'm getting that it's 'off' by 2 in some situations.
myDate = new Date(1622513190000)
month = myDate.getMonth()
console.log(myDate)
console.log(month)
Returns:
2021-06-01T02:06:30.000Z
4
Anyone have an idea why this is returning 4 and not 5? I'm using node v14.15.5 and am getting the expected result for other dates (September is 8, August is 7)
Thanks!

Hi and welcome here :)
Working with dates and timezone is a bit tricky, everyone here can attest it. For general information, I suggest you to read this article about Coordinated universal time.
The Z you can see in myDate value means Zulu time, military name for UTC±00:00, the reference timezone. ±00:00 represents an eventual offset with the Zulu time.
After having gone crazy about this question, I advice you to :
always get and store dates in Zulu format, and then compute time lapse with them
you can show users local dates, but it's only to display them. If you have to compute with a user input, first get the UTC equivalent (as #RobG advised).
Good luck ! :)

Related

Javascript getTime() delivers confusing results

I've searched a lot, but couldn't find an explanation for this, in my opinion confusing behavior of getTime(). The documentation states:
getTime() always uses UTC for time representation. For example, a
client browser in one timezone, getTime() will be the same as a client
browser in any other timezone.
According to this statement, my understanding is, that e.g.
1. new Date (Date.UTC(2021,8,1)).getTime() // UTC Date 1.Sep.2021 00:00:00
2. new Date (2021,8,1).getTime() // Local (UTC+1) Date 1.Sep.2021 00:00:00
should deliver the same amount of milliseconds. But the results I'm getting are these:
1. 1630454400000
2. 1630447200000 // 1 hour (3600000 ms) missing
Question A: Physically the same amount of time has passed since 1.1.1970. Why are the results not equal (also daylight saving matters!) like they should, according to the docs?
Question B: If the behavior is correct, why is there one hour missing? Shouldn't there be one hour more? Logically UTC+1 is one hour ahead.
Ok, I found out what caused the confusion. Thanks for all your help! Especially to Chris G who pointed me in the right direction. Here is what screwed up my brain ;-)
All who didn't understand why there is an issue at all, were most likely looking at this from a regular webrowser user's point of view. In that scenario if a user in UTC+1 opens a website which calls getTime() at lets say 1. Sept. 2021 07:00:00, that would result in this:
now Date ( 2021, 8, 1, 7, 0, 0 ).getTime()
Now if a second user does the same at exactly the same moment in UTC+0, this would result in:
now Date ( 2021, 8, 1, 6, 0, 0 ).getTime()
Then of course we are getting the same results! My problem was that I assumed that calling:
now Date ( 2021, 8, 1, 7, 0, 0 ).getTime()
in different time zones should give the same result. Which is NOT the case! Now you may ask why someone would need this. The reason is simple. I'm developing a little Gantt tool in Electron and there I need to compare/subtract dates. Of course I don't need the above to be true (deliver the same values), but I came accross this problem, because I was not getting divisable numbers of milliseconds when subtracting dates by converting them to ms with getTime(). I was expecting that according to the doc, which says that getTime() will give the same value in every time zone, to get an absolute value which is not influenced by time zones or daylight saving, for calculation. Thus I expected that e.g.:
now Date(2021,4,1,0,0,0).getTime() - now Date(2021,11,1,0,0,0).getTime()
Should give a number of milliseconds, which should be perfectly divisiable by 86400000 (one day). But that was not the case. The reason is that the second date is 1h behind because of daylight saving!
Conclusion
The statement in the doc is true when looking at the same point in time (e.g. UTC+0
06:00 and UTC+1 07:00), but not when looking at the same number of hours (e.g. UTC+0
07:00 and UTC+1 07:00). That was what confused me. Maybe this explanation helps others as well.

Javascript new date from month and year string

I bumped into a situation where I'm getting a string indicating only the month and year of a date, and I need to create a Date object out of it. If I pass just the string, e.g. "February 2020" into a Date constructor, I strangely get back the the day of the previous month, i.e. in this case 2020-31-01. Thus, I need to always add 1 day to get the proper month in the Date object.
Here is the code to replicate:
var date_str = "February 2020";
var dt = new Date(date_str)
console.log(dt) // Returns : 2020-01-31T23:00:00.000Z (????)
dt.setDate(dt.getDate() + 1);
console.log(dt) // Returns : 2020-02-01T23:00:00.000Z
Any idea what the logic is behind this rather strange behaviour, or do I miss something here?
Update
Have accepted the first answer as being relevant, thus the main question is solved. However, just to add to the confusion: the code snippet I included runs as described with node. Using EXACTLY the same logic in a Vue.js application return the correct Date. Very strange!
"February 2020" is not a valid input according to the specification thus you should not rely on it to work.
You should convert your input to one that is according to spec and then decide whether you need local time or UTC.
Handling time(zones) is one of the hardest things in JavaScript and I strongly recommend that you do not try to reinvent the wheel here yourself as it is really easy to mess up.
Libraries like momentjs can help you here.
Actually you are passing February 2020 into the date Constructor , and its assumes the
date as 1 February 2020 thus it give the output as its UTC date which may be previous
day depending on your region
Use moment.js library, it will give perfect.
moment("February 2020").format('L')
"02/01/2020"

Comparing 2 dates with momentJS

I am trying to compare a DAY/TIME e.g. Monday 09:00:00 with the current time to see if I am past that point in the week. e.g. If it is now 05:00:00 on Monday it should return true however it is returning false everytime
var dayTime = Moment("Wednesday 17:00:00", "dddd HH:mm:ss");
var now = Moment(Moment.now(), "dddd HH:mm:ss");
console.log(Moment.utc(dayTime).isBefore(now)); //returns false all the time
I found the following similar questions but it didn't seem to fix the issue after formatting the time.
Comparing two times with Moment JS
When I replace the moment.now() with a string such as "Wednesday 17:00:00" it returns the expected result.
Any idea what I need to do to moment.now() in order for this to work correctly?
Moment.now can be used as an extension point, but it's really not a public API. To get the current time in momentjs you just call moment(). Note that all moment calls use lowercase moment.
To see if your date and time is before the current time, you would just call:
moment('01/01/2016', 'MM/DD/YYYY').isBefore(moment())
You would replace the date and format in question with your own.
I see that you have a date format that includes only day of week and time. Moment will parse this, but be aware that the behavior might not be what you expect. When I parse your date, I get Wednesday December 30, 2015. Exactly what day this lands on will vary by locale. In any case, I doubt that it is what you want. If at all possible, I would get year, month, and day.
If you would like to instead set the moment to Wednesday this week, set the day on the moment using .day(). For instance:
moment().day(3).format()
"2016-06-15T20:19:55-05:00"
For anyone who is interested, the code I posted in my question was changing the day/hour but was setting the year to 2015 which meant that it was always in the past.
To fix I separated out the Day and the Hour and set to moment. Then compared that with now. e.g.
moment().set({"Day": "Friday", "Hour": "17"}).isBefore(moment())

momentjs days difference between two GMT dates

I'm trying to get difference of days between two GMT dates using moment
but I couldn't find it.
I'm on IST(+05:30) and I have some GMT dates(-05:00) in db,
I tried using following command
temp2.diff(temp1, "days")
here is a screenshot of all the commands tried in console
there we can clears see that dates are different and still shows the difference is 0
here is how I'm initializing moment objects of 'America/New_York'
var temp1 = moment.tz(new Date('Mon Jan 25 2016 22:00:00 GMT-0600'), 'America/New_York');
var temp2 = moment.tz(new Date('Tue Jan 26 2016 00:00:00 GMT-0600'), 'America/New_York');
any help appreaciated, thanks.
Well, there is less than 24 hours difference between those dates, so it's correct. The documentation says:
By default, moment#diff will return number rounded down. If you want the floating point number, pass true as the third argument.
> temp2.diff(temp1, "days", true)
0.08333333333333333
If you don't care about the hours at all, set them to 0 before you do the comparison
> temp2.hours(0).diff(temp1.hours(0), "days")
1
A few things:
You say that you are retrieving these values from a database, but then you show us loading them via the Date constructor from a string value. If you are really storing a string in your database, especially in that particular format, then you have much larger problems than the one you asked about! Please show us precisely how you load the values from your database to begin with.
You shouldn't rely on the Date object for parsing, especially when you are already using moment, which has much better parsing routines of its own.
You said these values where in America/New_York, but then you show an offset of -0600. That's never used in that time zone. The offset for the value you showed would be -0500.
You also said "I have some GMT dates(-05:00)" - which doesn't make any sense. GMT is +00:00. GMT-0500 means "5 hours behind GMT". Thus, you no longer have a "GMT date".
Be aware that the JavaScript Date object can only use the time zone of where the code is running. You cannot run it in any other time zone.
While Felix is correct in how you can show decimals with the diff function, you should realize that diff is giving you the actual elapsed time between the two moments in time you asked about. However, you seem to be wanting to know the total number of calendar days separating the two days that the moments fall into within the named time zone. To do that, you'd need to ignore the time portion. Using startOf('day') is an easy way to do that. Consider:
var a = moment.parseZone("2016-01-25T23:00:00-05:00");
var b = moment.parseZone("2016-01-26T01:00:00-05:00");
b.diff(a, 'days', true) // 0.08333333333333333 (not what you want)
b.startOf('day').diff(a.startOf('day'), 'days') // 1 (that's better!)
moment(b).startOf('day').diff(moment(a).startOf('day'),'days') // 1 (best approach)
Note a few things with this code:
The code in the last line is the best approach, as it leaves the original values of a and b alone. Otherwise, they would be modified. (Moments are mutable.)
You seem to already have the correct local time and offset, and thus there's no need to use moment-timezone's tz function. You can just use parseZone. Of course if this was just a side effect of your example, then you could still use moment-timezone, but I'd strongly recommend against using the Date constructor still.

Which should be the correct date format for Date.parse?

Hey guys, Im having trouble knowing wat is the correct date format i should put for date.parse() function.
I want to use mm/dd/yyyy in the function like this.
alert("Date: "+Date.parse("11/28/2011"));
//-->Its showing me Date:NaN as output.
also I wanted to know what output should I be getting if I do this following code:
date = Date.parse('12/31/2011' +' UTC');
var minutes=1000*60;
var hours=minutes*60;
var days=hours*24;
var years=days*365;
var y=date/years;
t should give me exactly 42 years but its giving me decimal as well. Y so??
Any help will be appreciated guys.
Thanks
Anand
International (ISO) standard date time format will always work. 2011-12-31
You may also look at this and this
Why would it give you exactly 42 years? Don't forget that there's no such thing as an exact number of milliseconds in a year, due to leap years (and leap seconds, if they're accounted for). Even if there were, you're getting the start of the last day of 2011, which isn't the same as the start of the first day of 2012, which is probably what you were thinking of.
The exact formats supported are implementation-specific as far as I can tell - at least for ECMAScript (which I realise isn't quite the same as JavaScript).

Categories