Javascript Subtract/Add 1 month from date [duplicate] - javascript

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.

Related

Parsing datetime to Unix timestamp in JavaScript [duplicate]

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".

calculate back date using jquery

I have a requirement where I want to calculate back date.
For example if I am giving 5 months then it should return the 5 month back date and if i give 5 years then it should return the 5 years back date keeping leap year in mind.i tried to implement some of the examples which I found in web but non of them are giving me the exact result.
Can someone please help me to achieve so.
You can use setMonth setDate and setFullYear on a Date object easily.
The thing is, if you're adding a whole year, and it's a leap year, you'll still end on the same date (month and day) of the last year. which i think it's the correct behaviour.
now = new Date() // 2016-11-24T13:21:55.841Z
now.setFullYear(now.getFullYear() -1) // 2015-11-24T13:21:55.841Z
If you want to subtract a standard-sized-year, I think you should instead remove 365 days from the current day. Which will take you to a slightly different date.
now = new Date() // 2016-11-24T13:21:55.841Z
now.setDate(now.getDate() - 365) // 2015-11-25T13:21:55.841Z

later.js - February and End of Month

I am creating a platform for recurring monthly orders.
I am using later.js for the recurrence. I have come across the following two cases and I am wondering if anybody has suggestions on how to better handle these (or if later.js handles them natively somehow):
later.parse.recur().on(31).dayOfMonth()
The date is the 31st of a given month. Current result is that is jumps months that end on the 30th. WORKAROUND: is to use last().dayOfMonth().
later.parse.recur().on(30).dayOfMonth()
later.parse.recur().on(31).dayOfMonth()
Month of February, ending on the 28th or 29th. How to handle if the date is 30th (or 31st). WORKAROUND: If date > 28th, add .and().on(59).dayOfYear()
Thanks!
I don't know the specifics of later.js, but apparently you can write something called a custom modifier: https://github.com/bunkat/later/blob/master/example/modifier.js
In addition to this, if you add a month to a javascript date (doesn't matter if the number becomes greater than 11/december), set the day of the month to the first then subtract 1 day, then you'll get the date of the last day in the originally given month. For example:
var a = new Date("2000-02-25");
var b = new Date(new Date(a.getFullYear(),a.getMonth()+1,1)-1);
console.log(b);

Adding months to setMonth of javascript showing a 0

I'm running to an issue I'm not sure how to resolve it; so the deal is that I have a function of javascript that take the date selected from the user and depending of another selection it adds to the date 6 o 12 months, the weird thing is that when you select a date of June, and make it add the 6 months I get a return value of 0 months, and it should be 12 for December, also If you choose December and add 12 months I'm getting a 0 as a return value. So here is my code
var date1 = $("#date_begin").val();
var days= date1[0] + date1[1];
var month= date1[3] + date1[4];
var year= date1[6] + date1[7] + date1[8] + date1[9];
var actualDate = new Date(year,month,days);
actualDate.setMonth(actualDate.getMonth() + 6);//add 6 months
$("#date_finish").val(actualDate.getDate()+"-"+actualDate.getMonth()+"-"+actualDate.getFullYear());
I'm printing the date directly to the text box as you can see. Also for the selection of the date in the first box I'm using the datepicker of jquery with this option selected
$("#date_begin").datepicker("option", "dateFormat", "dd-mm-yy");
I have been trying to fix this but I have no idea how to do it.
Hope you guys can give me a hand.
Months are indexed from 0.
June is 5 not 6.
What you have calculated is actually July (6) + 6 months = January (0) of the next year.
If you can get the date string into a format accepted by Date's constructor, that might be an easier way to create your date object. Though you need to be aware that there are some differences between browsers when it comes to the formats that are accepted.
If the date comes from users, then you should use a date format that makes sense for your users, and if necessary use a library that can work with that format of date.
When the date comes from communications with the server, I like to use the same format produced by JSON.stringify (dates that look like 2015-06-09T21:42:25.816Z), and I use es5-shim.js to make sure that the new Date(string) constructor can read strings in that format.
There is some information about parsing date strings using the new Date(string) constructor on Mozilla's developer site.

Day overflows in javascript Date constructor

I am currently writing some sort of javascript based client calendar and observed some issues. All over the net, I can find code samples, where people use day overflows in the Date constructor.
i.e.
// get the first day of the next month
var myDate = new Date(someDate.getFullYear(),someDate.getMonth(),32);
myDate.setDate(1);
The general idea of this concept is, that since there is no month with 32 days, the constructor will create a date within the next month. I saw even codesample with negative overflows:
i.e.
// get the last day of the previous month
var myDate = new Date(someDate.getFullYear(),someDate.getMonth(),1);
myDate.setDate(-1);
Now while this seems to work in many cases, I finally found a contradiction:
// this prints "2012-12-30" expected was "2012-12-31"
var myDate = new Date(2013,0,1);
myDate.setDate(-1);
Further examination finally revealed that dates like
new Date(2013,0,23) or new Date(2013,0,16) combined with setDate(-1) all end up in "2012-12-31". Finally I observed that using -1 seems to subtract two days (for getting the expected result setDate(0) has to be used).
Is this a bug in the browser implementations or are the code samples spread accross the internet crap??
Furthermore, is this setDate with positive and negative overflow secure to be used and uniformly implemented by all major browsers?
From MDN:
If the parameter you specify is outside of the expected range, setDate attempts to update the date information in the Date object accordingly. For example, if you use 0 for dayValue, the date will be set to the last day of the previous month.
It's logical if you think about it: setDate(1) sets the date to the first of the month. To get the last day of the previous month, that is, the day before the first of this month, you subtract one from the argument and get 0. If you subtract two days (1 - 2) you get the second to last day (-1).
are [..] code samples spread accross the internet crap?
Yes. This is true at least 90% of the time.
At MDN they say:
If the parameter you specify is outside of the expected range, setDate
attempts to update the date information in the Date object
accordingly. For example, if you use 0 for dayValue, the date will be
set to the last day of the previous month.
So you're getting coherent results:
1 - Jan 1
0 - Dec 31
-1 - Dec 30
-2 - Dec 29
Edit: It may look counter-intuitive if you think of it as a mere relative value, such as PHP's strtotime() function:
strtotime('-1 day');
It's not the case ;-)

Categories

Resources