I'm trying to find the difference between today and a date in the future (number of days) using moment.js.
But the response is always off by 1-2 days.
For instance, trying to find the # of days between today (15 June) and 11th July gives me 25 days whereas it should be 27 days.
Here's what I am using
moment(expiryDate).diff(moment(), 'days');
expiryDate is a string of the format YYYY-MM-DD
I am assuming the difference is because the dates themselves are not included? But nothing in the moment.js document suggests this. Neither did I find anything by which I can tell the library to calculate the difference inclusive of the dates.
This should do the trick
console.log(
moment("2020-07-11", 'YYYY-MM-DD').diff(moment("2020-06-15", 'YYYY-MM-DD'),"days")
) // outputs 26 (which is correct)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js"></script>
Related
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.
I stumbled upon an interesting issue with moment.js in a node.js environment. Basically, I'm trying to get the time from epoch for a date format "Friday 24 Aug", but I receive NaN as a result. Here is my node.js code:
const moment = require("moment");
console.log(moment("Friday 24th Aug", "dddd Do MMM").valueOf());
moment.js version: 2.23.0
nodejs version: v8.11.3
OS: Linux 16.04.1-Ubuntu
While if I try the same console line on a browser, works fine. Has anyone stumbled upon something like this?
EDIT: Apologies for the link, I used an already created jsfiddle which had moment.js version: 2.2.1. It seems it had "worked" in that version, but now it's changed: http://jsfiddle.net/fy8w62on/ (moment.js version 2.2.1)
valueOf() gives NaN because your moment object (moment("Friday 24th Aug", "dddd Do MMM") is invalid.
Please note that, as Default section of the docs states:
You can create a moment object specifying only some of the units, and the rest will be defaulted to the current day, month or year, or 0 for hours, minutes, seconds and milliseconds.
so moment tries to create an instance representing 2019-08-24 (using current year), but it creates an Invalid Date because 2019-08-24 is Saturday (using default English US locale), not Friday (as already stated by others in the comments).
Using parsingFlags you will see that weekdayMismatch is set to true
var m = moment("Friday 24th Aug", "dddd Do MMM");
console.log(m.valueOf()); // NaN
console.log(m.format()); // Invalid date
console.log(m.parsingFlags()); // Object with "weekdayMismatch": true
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
Friday 24th Aug does not contain a year so moment has to guess what year it is and uses the current year for the guess.
If it is 2018 at the time when you run the code then valueOf would not return NaN.
But it is 2019 so Friday 24th Aug of 2019 is not valid.
I have a date in the following format var timestamp = "6/9/2016 1:47:31 PM";. I'm trying to get the relative time (4 hours ago, 3 minutes ago, 3 days ago, etc...) from the timestamp compared to the current datetime using from now.
var LastReading = moment(timestamp).fromNow();
but this is returning "2010 years from now". I tried using the format
var LastReading = moment(timestamp, "MM/DD/YYYY HH:mm:ss").fromNow();
but I get the same result. Any ideas? Do I need to format the date in a different way in order to get the fromNow method to work as expected?
To match your timestamp, the format should look like this:
MM/DD/YYYY hh:mm:ss A
HH means 24 hour time, but you're using 12 hour time, for which you need to use hh. Also, A will match AM/PM.
It seems to me that Date.parse assumes all months have 31 days. Including months with 30 days and including February(which should only ever have 28/29 days).
I checked this question 31 days in February in Date object
But the answer there suggested there was nothing wrong with Date in his issue..Somebody said something to the questioner about zero indexing and he pretty much said "oh ok", and determined that it was his mistake and not a mistake of Date.
Another question Date is considering 31 days of month the guy was doing some subtraction was a number of lines of code and he seemed to not put the error down to Date in the end.
But this example that I have seems to be a bit different and more clear cut. It involves Date.parse and can be demonstrated with one/two lines of code.
Date.parse is aware that there are not 32 days in a month, that's good
Date.parse("2000-01-32");
NaN
But In February it thinks there can be 30 or 31 days
Date.parse("2013-02-30");
1362182400000
Date.parse("2013-02-31");
1362268800000
In fact it looks like it thinks all months have 31 days. That is really strange for a method that is meant to parse a date.
And there's no issue of zero indexing here. As Date.parse("...") doesn't use zero indexing (And even if it did, it wouldn't cause it tot make the error of thinking there are 31 days in February - that is more than one off!
Date.parse("01-00-2000");
NaN
Date.parse("00-01-2000");
NaN
According to the specification for Date.parse() (emphasis mine):
The function first attempts to parse the format of the String according to the rules called out in Date Time String Format. […] Unrecognisable Strings or dates containing illegal element values in the format String shall cause Date.parse to return NaN.
And according to the specification for Date Time String Format (emphasis mine):
ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
Where the fields are as follows: […] DDis the day of the month from 01 to 31.
Therefore, any date with a day of month greater than 31 is illegal and Date.parse() returns NaN.
Please notice that the standard defines a date format, not a date: the static method isn't required to make additional verifications, and everything else is implementation-specific. For instance, Date.parse('2013-02-30') and Date.parse('2013-04-31') both return NaN on Firefox.
The implementation differs between browsers. IE, Edge and Chrome will parse strings that doesn't represent actual dates, but Firefox will return NaN for those strings. The safe thing to do is to consider the result from Date.parse as undefined for date strings where the day falls outside the range of the month.
Browsers that allow parsing of non-existent dates will return a different date. Parsing "2015-04-31" will return the date 2015-05-01. This is the same behaviour as when using new Date(2015, 3, 31), where numbers out of range is allowed and will wrap around into a different month or year. That means that the result is still usable, if you don't mind that some invalid dates turn into other dates in some browsers.
The standard isn't very clear about what values are valid:
Illegal values (out-of-bounds as well as syntax errors) in a format
string means that the format string is not a valid instance of this
format.
The day component is defined as having a range from 1 to 31:
DD is the day of the month from 01 to 31.
However, the format is based on ISO 8601, and that is not a format for parsing strings into dates, that is a format for representing dates as string. Clearly you can't represent a date that doesn't even exist as a string.
Right, so how to check if a date string has a valid value?
with moment is very easy:
export function dateStringIsValid(aDateString){
return (moment(aDateString, "DD/MM/YYYY", true).isValid())
}
I'm am trying to format a date in Javascript but the date command is returning the wrong date unless I use toUTCString() which returns the correct date, I've tried different ways of giving the date to the Date() function and both get and getUTC functions to get the date. I've also tried on different browsers (Chrome, Safari, FireFox) and what makes in even more confusing is if I do it in Chrome's inspector is works perfectly. And I missing something obvious?
var d = new Date(1324141200000);
// return "Sat, 17 Dec 2011 17:00:00 GMT" - Correct!
alert(d.toUTCString());
// returns "6-11-2011" - Wrong!
alert(d.getUTCDay() +'-'+ d.getUTCMonth() +'-'+ d.getUTCFullYear());
The "getUTCDay()" function returns the day of the week. The months are numbered from zero. Saturday is the sixth day of the week (in JavaScript land at least), and 11 is the 12th month counting from zero.
Thus, all is well.
The day of the month can be retrieved with "d.getUTCDate()".
d.getUTCDay() // day of week
d.getUTCMonth() // zero based index
Instead of getUTCDay, you want getUTCDate. And getUTCMonth returns 0-11 (0 = January). Section 15.9.1 of the specification may help, but the language is heavy-going.
Use
getFullYear()
function to get the year,
getMonth()
function to get the month, and
getDate()
function to get the day.