Javascript New Date() / UTC - GMT cross browser - javascript

The issue:
Different formats for new Date() in IE 10 - IE 11.
Javascript:
IE 11 / Chrome :
var m = new Date("2014-07-04T04:00:00");
console.log(m); // Fri Jul 04 2014 06:00:00 GMT+0200 (W. Europe Summer Time)
IE 10:
var m = new Date("2014-07-04T04:00:00");
console.log(m); // Fri Jul 4 04:00:00 UTC+0200 2014
Is possible to use one ring to rule them all?

You shouldn't pass a string to new Date, specifically for this reason.
Instead, you should either give it the individual arguments:
new Date(2014, 6, 4, 4, 0, 0); // remember months are zero-based
Or, if you want to give it a time in UTC, try:
var d = new Date();
d.setUTCFullYear(2014);
d.setUTCMonth(6);
d.setUTCDate(4);
d.setUTCHours(4);
d.setUTCMinutes(0);
d.setUTCSeconds(0);
d.setUTCMilliseconds(0);
You can, of course, make a function to do this.
Alternatively, if you have a timestamp, you can simply do:
var d = new Date();
d.setTime(1404446400000);

To complete the answer a bit. The UTC example given is dangerous, given that you execute on 31st of May (or any other 31st day of month) the following:
var d = new Date();
d.setUTCFullYear(2014);
d.setUTCMonth(5);
d.setUTCDate(4);
d.setUTCHours(4);
d.setUTCMinutes(0);
d.setUTCSeconds(0);
d.setUTCMilliseconds(0);
it will produce "2014 July 4 04:00:00".
So prefer Date.UTC function instead:
new Date(Date.UTC(2014, 5, 4, 4, 0, 0, 0))
it will produce "2014 June 4 04:00:00".

Related

js timezone - incorrect day getting

I have problem with boostrap- datepicker. The core of my problem in such example
var array = [2017, 12, 27];
var date = new Date(array);
console.log(date);
//Wed Dec 27 2017 00:00:00 GMT+0300 (RTZ 2 (winter))
var day = date.getUTCDate();
console.log(day);
//26 -> I WANT 27
console.log(month);
//11 -> I WANT 12
console.log(year);
//2017
As you can see at the end i get 26 (the day what i need is 27) and 11 (the month what i need is 12).
How can i change this code (remove my timezone) to get 27, 12, 2017
There are two problems you're running into:
The difference between your timezone (GMT+0300) and UTC means that midnight December 27th 2017 in your timezone is 9p.m. December 26th 2017 UTC.
I'm assuming you got month via getUTCMonth. Month values start with 0 = January, which is why you're getting 11.
To get midnight December 27th 2017 in a Date, use Date.UTC:
var dt = new Date(Date.UTC(2017, 12 - 1, 27));
console.log(dt.getUTCDate()); // 27
console.log(dt.getUTCMonth() + 1); // 12
console.log(dt.getUTCFullYear()); // 2017
Note the + 1 after getUTCMonth, since again, month numbers are 0 = January through 11 = December.

Subtracting 1 month to 2015-12-31 gives 2015-12-01

I'm trying to subtract one month from 2015-12-31 but it gives me 2015-12-01 instead of 2015-11-30. Why ?
Code:
var date1 = new Date('2015-12-31');
var date2 = new Date(date1);
date2.setMonth(date1.getMonth() - 1);
console.log(date1);
console.log(date2);
Output:
Thu Dec 31 2015 01:00:00 GMT+0100 (CET)
Tue Dec 01 2015 01:00:00 GMT+0100 (CET)
Any workaround?
When subtracting months, you can check whether the day of the adjusted Date is different to the day of the initial Date. If it is, then it must have rolled over to the next month, so set the day of the adjusted Date to 0, so it goes to the last day of the previous month, e.g.
function subtractMonths(date, months) {
var day = date.getDate();
date.setMonth(date.getMonth() - months);
if (date.getDate() != day) date.setDate(0);
return date;
}
// 31 Mar 2016 - 1 month = 29 Feb 2015
[[new Date(2016,2,31), 1],
// 29 Feb 2016 - 12 months = 28 Feb 2015
[new Date(2016,1,29), 12],
// 15 Feb 2016 - 3 months = 15 Nov 2015
[new Date(2016,1,15), 3]].forEach(function(arr){
document.write('<br>' + subtractMonths(arr[0], arr[1]));
})
The same algorithm can be used for adding months. Note that this is why date arithmetic is not symmetric, e.g.
31 May + 1 month => 30 June
30 June - 1 month => 30 May
i.e. If A + B = C, then C - B = A may or may not be true (and vice versa).
Try this
var date1 = new Date('2015-12-31');
var date2 = new Date(date1);
date2.setDate(date2.getDate()-date1.getDate());
alert(date2)
Per the setMonth documentation, ‘If you do not specify the [optional] dayValue parameter, the value returned from the getDate() method is used’. Since you’re not specifying the optional parameter, your code tries to set the date to 2015-11-31, which isn’t valid. JavaScript resolves this situation by setting the date to one day after 2015-11-30, which is 2015-12-01.
As for a workaround, it depends on what you’re actually trying to do. Are you trying to go 31 days back from 31 December? Or are you trying to get the last day of the month before December? Date semantics are extremely complicated; what are you going to do when the inevitable edge cases arise?
It is producing the requested result, which is subtracting 1 month from the date given. But remember a month is a variable amount of time. November 31 is actually December 1 (just like November 55th would actually be December 25, Christmas). To get the last day of the previous month you could do something like this:
var date = new Date('2015-12-31');
date.setDate(-1)

Does Javascript recognise leap years

I have the following snippet of code (actually I am using new Date() to get today (4th March 2016), but it won't be March for ever, so to be a sensible test I had made the date explicitly.
var n = new Date(2016,2,4);
var d = new Date (
n.getFullYear(),
n.getMonth(),
-1,
6,0,0);
console.log(d.toString());
when n is now (except it isn't) and d is a new date which I want to be the last day of the preceding month. I am NOT getting 29th February 2016 6:00am UTC, which is what I would have expected, instead I am getting 28th February.
This gives the same result in both Chrome and Iceweasel (Firefox). How should I find the last day of the previous month (especially, like this year when it is a leap year)
If it matters, I am in the GMT timezone.
That's because days are 1 based, not 0 based.
var march4 = new Date(2016, 2, 4);
var feb29 = new Date(
march4.getFullYear(),
march4.getMonth(),
0); // <-- go to the day before the first of the given month
console.log(feb29); // Mon Feb 29 2016 00:00:00 GMT-0700 (Mountain Standard Time)
For reference, if you pull the same trick for April to March, you'll get March 31st.
var april = new Date(2016, 3, 4);
var march = new Date(
april.getFullYear(),
april.getMonth(),
0);
console.log(march); // Thu Mar 31 2016 06:00:00 GMT-0600 (Mountain Daylight Time)
In fact, it recognizes
If you try this, it works:
Date (2016, 2, 0);
It brings to me Mon Feb 29 2016 00:00:00 GMT-0300
Instead of -1, try 0:
var n = new Date(2016,2,1);
var d = new Date (
n.getFullYear(),
n.getMonth(),
0,
6,0,0);
console.log(d.toString());

Moment.js months difference

I've been using moment.js for a short while now, and it's made date manipulation a lot easier but I have a specific case that is failing, and I can't see why.
When calculating the diff between today (31st October 2013) and the 1st February 2014, the months diff comes back as 2, although there are 3 complete months and one day between the two dates.
Diff between 31st October and 31st January works fine: 3 months and zero days.
var mStartDate = moment([ periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate() ]);
var mTermDate = moment([ someDate.getFullYear(), someDate.getMonth(), someDate.getDate() ]);
console.log('periodStartDate: ' + periodStartDate);
console.log('someDate: ' + someDate);
// Years
var yearsDiff = mTermDate.diff(mStartDate, 'years');
// Months
var monthsDiff = mTermDate.diff(mStartDate, 'months', true);
The console logs the following:
periodStartDate: Thu Oct 31 2013 11:13:51 GMT+0000 (GMT)
someDate: Sat Feb 01 2014 11:13:51 GMT+0000 (GMT)
monthsDiff: 2
If I pass true as the boolean not to round, the months diff is
monthsDiff: 2.983050847457627
Is this just a bug in Moment.js.diff()? Every single one of my other test cases pass successfully.
I think this has to do with the 'special handling' as described in The Fine Manual:
It is optimized to ensure that two months with the same date are
always a whole number apart.
So Jan 15 to Feb 15 should be exactly 1 month.
Feb 28 to Mar 28 should be exactly 1 month.
Feb 28 2011 to Feb 28 2012 should be exactly 1 year.
Moment.js applies this special handling when dealing with 31 Jan and 31 Oct (having the same day):
// 31 Oct 2013 - 1 Feb 2014
> moment([2014, 1, 1]).diff(moment([2013, 9, 31]), 'months', true)
2.983050847457627
// 31 Oct 2013 - 31 Jan 2014
> moment([2014, 0, 31]).diff(moment([2013, 9, 31]), 'months', true)
3
// 31 Oct 2013 - 30 Jan 2014
> moment([2014, 0, 30]).diff(moment([2013, 9, 31]), 'months', true)
2.967741935483871
So the 2.98 value is correct, it's just that the second example turns the result into a 'calender months' difference.
(as for rounding down to 2, that's also documented on the same page)
I went a different route trying to get the difference between two months
function getAbsoluteMonths(momentDate) {
var months = Number(momentDate.format("MM"));
var years = Number(momentDate.format("YYYY"));
return months + (years * 12);
}
var startMonths = getAbsoluteMonths(start);
var endMonths = getAbsoluteMonths(end);
var monthDifference = endMonths - startMonths;
This made sense to me and since moment is doing some strange things with diff I just decided to make it clear what my result will be.
Simple And Easy Solution with correct value difference between two months if you are using moment Library
const monthDifference = moment(new Date(endDate)).diff(new Date(startDate), 'months', true);
If you want to add the number of days in endDate
const monthDifference = moment(new Date(endDate.add(1, 'days'))).diff(new Date(startDate), 'months', true);
Try out this method;
function getMonthDifference(startDate, endDate) {
const increment = startDate.getMonth() === endDate.getMonth() ? 2 : 1;
const diff = moment(endDate).diff(moment(startDate), 'months', true);
return Math.ceil(diff) + increment; // this increment is opitional and totally depends on your need.
}

Javascript DATE add AM PM

I am doing a check of two different date times to see if one is greater than the other:
Here is my (now) current date time: Thu Aug 01 2013 10:27:40 GMT-0500 (CDT)
And here is my date time that I am seeing if it is greater or less than: Thu Aug 01 2013 12:15:00 GMT-0500 (CDT) - (that should be 12:15 am by the way)
Here is my code:
var current_date_time = new Date();
var date_time_checking_against = new Date(date_segment[0], date_segment[1]-1, date_segment[2], time_segment[0], time_segment[1]);
Which comes out to Thu Aug 01 2013 12:15:00 GMT-0500 (CDT). And then I am doing a simple if check:
if(current_date_time >= date_time_checking_against){ }
This is not working as 10:27:40 is not after 12:15:00. But it should be, seeing as how both times are AM. I need to know if this is the right way, or if there is a way to change it to 24 hour format or add am pm in there somehow. Any help is greatly appreciated, let me know if you need more clarity.
Thanks!
EDIT:
Here is the date time array:
var date_time_str = date+' '+time;
date_time_str = date_time_str.split(' ');
["2013-08-01", "12:15", "am"] // result from split above
var date_segment = date_time_str[0].split('-');
var time_segment = date_time_str[1].split(':');
var date_time_checking_against = new Date(date_segment[0], date_segment[1]-1, date_segment[2], time_segment[0], time_segment[1]);
Given the following data sources, this is how you'd properly create the Date object for it...
date_time_str = ["2013-08-01", "12:15", "am"];
var date_segment = date_time_str[0].split('-');
var time_segment = date_time_str[1].split(':');
var date_time_checking_against = new Date(
date_segment[0], // year
date_segment[1]-1, // month of year
date_segment[2], // day of month
(time_segment[0]%12) + (date_time_str[2] == 'pm' ? 12 : 0), // hour of day
time_segment[1]); // minute of hour
console.log(new Date() >= date_time_checking_against); // true, we've already passed this time

Categories

Resources