Through the 'date-fns' module, I am receiving numbers of how many weeks the date is this year.
const current = '2022-03-10'
const weekNumber = getWeek(current, 1) // 11
On the contrary, if you only know the numbers, you want to know how to do the first date of the week number.
The way I want to know.
const weekNumber = 11;
const weekOfstartDate = anyFunc(weekNumber) // '2022-03-07'
Do you know the answer to this solution?
You can use the I token:
var dateFns = require("date-fns");
console.log(dateFns.parse('10','I', new Date()));
At npm.runkit.com that returns a date for Mon 7 Mar 2022. It seems date-fns assumes the year of the current week. I have no idea how to specify the year, attempting:
console.log(dateFns.parse('2022-10','YYYY-II', new Date(),{
useAdditionalWeekYearTokens: true
}));
Throws a range error: The format string mustn't contain YYYY and II at the same time. Similarly for "2022W10" and tokens "YYYY'W'II", it says Y and I tokens can't be in the same format string.
A function to do the same thing is:
// Returns the first day (Monday) of the specified week
// Year defaults to the current local calendar year
function getISOWeek(w, y = new Date().getFullYear()) {
let d = new Date(y, 0, 4);
d.setDate(d.getDate() - (d.getDay() || 7) + 1 + 7*(w - 1));
return d;
}
// Mon Mar 14 2022
console.log(getISOWeek(11).toString());
// Mon Jan 02 2023
console.log(getISOWeek(1,2023).toString());
// Mon Dec 28 2026
console.log(getISOWeek(53,2026).toString());
A robust function should validate the input such that the week number is 1 to 53 and that 53 is only permitted for years that have 53 weeks.
I wanted a solution only using date-fns functions. This is how i combined it:
const result = setWeek(nextMonday(new Date(year, 0, 4)), week, {
weekStartsOn: 1,
firstWeekContainsDate: 4,
});
I am using Bootstrap Datepicker, and based on the date selection I need to display a message to the user.
I have never used the Date Constructor before so it's very new to me.
What I need to do is the following;
allow user to select a date
display a message / alert based of the logic below
If their selected date is within the last 6 months of today, they quality for discount.
If their selected date doesn't fall within the last 6 months of today, they don't.
Although it's not working correctly have created a fiddle here.
Any help would be appreciated. Code also below;
HTML
<input type="text" class="form-control" id="datepicker" placeholder="Year Graduated" value="" data-date-format="dd/mm/yyyy">
<p id="rate"></p>
JS
function compareDate() {
// get date from datepicker
var dateEntered = $("#datepicker").datepicker("getDate");
dateEntered = new Date(dateEntered).getTime();
//alert("date entered: " + dateEntered);
// set todays date
var now = new Date();
// set date six months before today
var sixMonthBeforeNow = new Date(now).setTime(now.getTime() - 3 * 28 * 24 * 60 * 60);
//alert("six months before: " + sixMonthBeforeNow);
// if date entered is within six months from today
if (dateEntered > sixMonthBeforeNow) {
alert("You qualify for the discount rate.");
$("#rate").html('discount rate');
}
// if date entered is over six months from today
if (dateEntered < sixMonthBeforeNow) {
alert("you graduated more than six months ago");
$("#rate").html('no discount');
}
}
$("#datepicker").datepicker({
weekStart: 1,
daysOfWeekHighlighted: "6,0",
autoclose: true,
todayHighlight: true
});
$("#datepicker").change(function() {
compareDate();
});
Note: I'd prefer not to use any other 3rd party JS library / plugin.
Just change your sixMonthBeforeNow with the below code, that should work.
var sixMonthBeforeNow = new Date(now).setMonth(now.getMonth() - 6);
You need to be careful with date arithmetic because it's not symmetric due to the uneven length of months, so you need rules to deal with it. E.g. what date is exactly 6 months before 31 August?
Before answering, consider:
28 February plus 6 months is 28 August
1 March plus 6 months is 1 September.
So what date is 6 months before 29, 30 and 31 August? Is it 28 February or 1 March?
Similar issues arise for any last day of a month where the month 6 months previous doesn't have 31 days. Should the limit be the 30th of the month or the 1st of the following month? When you've answered that question, then you can devise an algorithm to deliver the right answer and then the code to implement it.
If you want such cases to set the date to the end of the month 6 months before, then you can check the month resulting from subtracting 6 months and if it's not 6, set it to the last day of the previous month, e.g.
function sixMonthsPrior(date) {
// Copy date so don't affect original
var d = new Date(date);
// Get the current month number
var m = d.getMonth();
// Subtract 6 months
d.setMonth(d.getMonth() - 6);
// If the new month number isn't m - 6, set to last day of previous month
// Allow for cases where m < 6
var diff = (m + 12 - d.getMonth()) % 12;
if (diff < 6) d.setDate(0)
return d;
}
// Helper to format the date
function formatDate(d) {
return d.toLocaleString(undefined, {day:'2-digit', month:'short', year:'numeric'});
}
// Tests
[ new Date(2018, 7,31), // 31 Aug 2018
new Date(2018, 8, 1), // 1 Sep 2018
new Date(2018,11,31), // 31 Dec 2018
new Date(2019, 2,31) // 31 Mar 2019
].forEach( d => console.log(formatDate(d) + ' => ' + formatDate(sixMonthsPrior(d))));
If that is't the logic you wish to apply, you need to say what is.
PS. You can also implement the above logic by just comparing the start and end dates (day number). If they're different, it must have rolled over a month so set to 0.
I can get the difference between two dates using moment.js or plain js.
in moment.js
var a = moment(timestamp1);
var b = moment(timestamp2);
var month =a.diff(b, 'month');
var day =a.diff(b, 'day') - month;
var year =a.diff(b, 'hours');
month returns month , days return difference in days . But I want the answer in
MM-DD-hh format for example 2 months 12 days 5 hours . I can not convert the day directly cause there is other issues like leap year . Is there any other way then going all out and calculating everything ? I am doing this in angular js if that is of any help
Getting the precise difference between two dates is not simple as years, months, and days have different lengths. Also, adding is not necessarily symmetric with subtraction, e.g. is 30 April plus one month is 30 May, but is 31 May plus one month 30 June or 1 July? Similar with 29 Feb plus or minus 1 year.
The following tries to deal with those issues, so that if adding a month rolls over an extra month, the date is returned to the last day of the previous month. Hopefully the comments are sufficient, if not, ask for clarification.
The dateDiff function returns an array of the values for years, months, days, etc. To get MM-DD-hh, just get that and format it any way you want. I've included a small formatting function that just prints out the non–zero components.
// Simple calculation of days between two dates based on time value
function getDaysDiff(start, end) {
return ((parseStringUTC(end) - parseStringUTC(start))/8.64e7).toFixed(2);
}
// Expects input in ISO8601 format: yyyy-mm-ddThh:mm:ss.sssZ
// Always expects UTC
function parseStringUTC(s) {
s = s.split(/\D/);
s[6] = s[6]? ('0.'+ s[6]) * 1000 : 0;
return new Date(Date.UTC(s[0],--s[1],s[2],s[3]||0,s[4]||0,s[5]||0,s[6]||0));
}
/* Get the difference between two dates in years, months, days,
** hours, minutes and seconds.
**
** Difference is values to add to earlier date to reach later date.
**
** Does not consider daylight saving changes so may be incorrect by offset
** difference over daylight saving boundaries, so use UTC values (pass
** values as date.toISOString() or format like ISO 8601 UTC)
**
** #param {string} d0 - earlier date in format y-m-d h:m:s, can also be
** yyyy-mm-ddThh:mm:ssZ, the timezone offset is ignored
** the string is not validated
** #param {string} d1 - later date in same format as above. If d1 is earlier
** than d0, results are unreliable.
** #returns {Array} values for years, months, days, hours, minutes and
** seconds (milliseconds as decimal part of seconds)
*/
function dateDiff(d0,d1) {
var s = d0.split(/\D/);
var e = d1.split(/\D/);
// Calculate initial values for components,
// Time component is optional, missing values treated as zero
var ms = (e[6]||0) - (s[6]||0);
var sec = (e[5]||0) - (s[5]||0);
var min = (e[4]||0) - (s[4]||0);
var hr = (e[3]||0) - (s[3]||0);
var day = e[2] - s[2];
var mon = e[1] - s[1];
var yr = e[0] - s[0];
// Borrowing to resolve -ve values.
if (ms < 0) { // ms borrow from sec
ms += 1000;
--sec;
}
if (sec < 0) { // sec borrows from min
sec += 60;
--min;
}
if (min < 0) { // min borrows from hr
min += 60;
--hr;
}
if (hr < 0) { // hr borrows from day
hr += 24;
--day;
}
// Day borrows from month, a little complex but not too hard
if (day < 0) {
var prevMonLen = new Date(e[0], e[1]-1, 0).getDate();
// If the start date is less than the number of days in the previous month,
// set days to previous month length + current diff days value
// Note that current diff days may have had a day borrowed, so don't use end date - start date
// Otherwise, if the start date is equal to or greater than the number of
// days in the previous month, just set to end date. That's because adding
// 1 month to 30 Jan should be last day in Feb (i.e. 28 or 29), not 2 or 1 March
// respectively, which is what happens if adding 1 month to a Date object for 30 Jan.
// Similarly, 31 May + 1 month should be 30 June, not 1 July.
day = s[2] < prevMonLen? prevMonLen + day : +e[2];
--mon;
}
if (mon < 0) { // mon borrows from yr
mon += 12;
--yr;
}
// If days >= number of days in end month and end date is last day
// of month, zero mon and add one to month
// If then months = 12, zero and add one to years
var endMonLen = new Date(e[0], e[1], 0).getDate();
if (day >= endMonLen && s[2] > e[2] && e[2] == endMonLen) {
day = 0;
++mon;
if (mon == 12) {
mon = 0;
++yr;
}
}
return [yr,mon,day,hr,min,+(sec + '.' + ('00'+ms).slice(-3))];
}
/* Format output from dateDiff function, e.g. 3years, 2 days, 23.12 seconds
**
** #param {Array} v - values array in order years, months, days, hours, minutes
** seconds (milliseconds as decimal part of seconds)
** #returns {string} Values with their names appended. Adds "s" to values other
** than 1, zero values omitted, e.g. "0 months" not returned.
*/
function formatOutput(v) {
var values = ['year','month','day','hour','minute','second']
return v.reduce(function (s, x, i) {
s += x? (s.length? ' ' : '') +
(i == 5? x.toFixed(3) : x) + ' ' + values[i] + (x==1?'':'s'):'';
return s;
}, '');
}
// Tests, focus on February
var dates = [
['2016-01-31','2016-03-01'], // 1 month 1 day - 31 Jan + 1 month = 29 Feb
['2016-01-29','2016-03-01'], // 1 month 1 day - 29 Jan + 1 month = 29 Feb
['2016-01-27','2016-03-01'], // 1 month 3 days - 27 Jan + 1 month = 27 Feb
['2016-01-27','2016-03-29'], // 2 months 2 days - 27 Jan + 2 month = 27 Mar
['2016-01-29','2016-03-27'], // 1 month 27 days - 29 Jan + 1 month = 29 Feb
['2015-12-31','2016-01-30'], // 30 days - 31 Dec + 30 days = 30 Jan
['2015-12-27','2016-01-30'], // 1 month 3 days - 27 Dec + 1 month = 27 Jan
['2016-02-29','2017-02-28'], // 1 year could also be 11 months 30 days
// since 29 Feb + 11 months = 28 Feb, but 28 Feb is last day of month
// so roll over to full year
// Both work, but 1 year is more logical
['1957-12-04','2016-02-20'], // 58 years 2 months 16 days
['2000-02-29','2016-02-28'], // 15 years 11 months 30 days
// Not full year as Feb 2016 has 29 days
['2000-02-28','2016-02-28'], // 16 years
['2000-02-28','2016-02-29'], // 16 years 1 day
['2016-02-28T23:52:19.212Z','2016-12-02T01:48:57.102Z'] // 9 months 3 days 1 hour 56 minutes 37.899 seconds
];
var arr = [];
dates.forEach(function(a) {
arr.push(a[0] + ' to ' + a[1] + '<br>' + formatOutput(dateDiff(a[0], a[1])));
});
document.write(arr.join('<br>'));
table {
border-collapse:collapse;
border-left: 1px solid #bbbbbb;
border-top: 1px solid #bbbbbb;
}
input {
width: 12em;
}
input.bigGuy {
width: 32em;
}
td {
border-right: 1px solid #bbbbbb;
border-bottom: 1px solid #bbbbbb;
}
td:nth-child(1) { text-align: right; }
<form onsubmit="this.doCalc.onclick(); return false;">
<table>
<tr>
<td width="250"><label for="startDate">Start date (yyyy-mm-dd)</label>
<td><input name="startDate" id="startDate" value="2012-08-09T22:15:03.22" size="25">
<tr>
<td><label for="endDate">End date (yyyy-mm-dd)</label>
<td><input name="endDate" id="endDate" value="2013-08-13T12:10:03.22" size="25">
<tr>
<td><label for="dateDifference">Date difference: </label>
<td><input name="dateDifference" readonly class="bigGuy">
<tr>
<td><label for="daysDifference">Days difference: </label>
<td><input name="daysDifference" readonly>
<tr>
<td>
<input type="button" value="Calc date difference" name="doCalc2" onclick="
this.form.dateDifference.value = formatOutput(dateDiff(this.form.startDate.value, this.form.endDate.value));
this.form.daysDifference.value = getDaysDiff(this.form.startDate.value, this.form.endDate.value) + ' days';
">
<td><input type="reset">
</table>
</form>
Some things to note:
31 May to 30 June is 1 month. It doesn't make sense for it to be 1 July.
In a leap year, 31 Jan to 29 Feb is 1 month, to 28 Feb 2016 is 28 days.
Not in a leap year, 31 Jan to 28 Feb is 1 month.
29 Feb 2016 to 28 Feb 2017 is 1 year, since 28 Feb is the last day of the month
29 Feb 2016 to 28 Feb 2020 is 3 years, 11 months and 30 days since 28 Feb is not the last day of the month in 2020.
This solution can be implemented entirely without using Date objects, I've just used it for convenience for getting the days in a month, but an alternative that doesn't use a Date is about 4 lines of code.
var date1 = new Date("4/14/2016");
var date2 = new Date("10/16/2016");
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var newDate = new Date(timeDiff);
alert(newDate);
alert("Month " + (newDate.getUTCMonth() + 1));
alert("Date " + newDate.getUTCDate());
alert("Hour " + newDate.getUTCHours());
you cannot convert a difference (diff result is a number) to MM-DD-hh format, because some months are 30 day length, the others are 31 day length.
It could be calculated from start and end datetime.
There's a similar function what you are looking for, but not exact
moment("2010-01-01").from("2010-12-01")
result: a year ago
moment("2010-01-01").from("2010-12-01", true)
result: a year
I have this script for selecting date.
<script type='text/javascript'>
$(function () {
$("#datepicker").datepicker({
minDate: "-5M",
maxDate: "-1M",
changeMonth: true,
changeYear: true
});
});
function Image13_onclick() {
}
</script>
this allows me to select any date from past five months. I want just one month for the user to select and that should be previous
month. For example if current month is March then datepicker should only have Feb.
Relative dates must contain value and period pairs; valid periods are "y" for years, "m" for months, "w" for weeks, and "d" for days. For example, "+1m +7d" represents one month and seven days from today.
So you only need to calculate the right min date and max date. JS Fiddle
$(function () {
var date = new Date();
var maxDate = "-" + date.getDate() + "D";
var minDate = "-1M " + "-" + (date.getDate() - 1) + "D";;
$("#datepicker").datepicker({
minDate: minDate,
maxDate: maxDate,
changeMonth: true,
changeYear: true
});
});
I have the function below which takes a string from the datepicker and turns it into a date object so I can add 30 days to it. From there I am trying to return the new date as a string with 30 days added to it, in the format of (mm/dd/yy).
When the first alert fires it correctly adds 30 days to the selected date and shows this for selcted date as "05/03/2011":
Thu Jun 02 2011 00:00:00 GMT+0100 (GMT Daylight Time)
The second alert shows
5/2/2011
Seems I can't correctly format the date and take "05/03/2011" and return "06/02/2011". I could just do month + 1, but could do with some help please and show me what I am doing wrong.
$('#sign_date').datepicker({
onSelect: function(dateText, inst) {
var d = new Date(dateText);
d.setDate(d.getDate() + 30);
alert(d);
var date = d.getDate();
var month = d.getMonth();
var year = d.getFullYear();
alert(month+'/'+date +'/'+year)
}
});
Also I think they way I am doing it will show days and month as e.g. Jan = 1 and 1st = 1 and I would like it to be Jan = 01 and 1st = 01
Thanks
For leading zeros:
// add leading zero if the length equals 1
if (month < 10) month = "0" + month;
if (day < 10) day = "0" + day;
Be sure to add 1 to your month prior to using this code, too, since getMonth() returns a 0 for January, and so on:
var month = d.getMonth() + 1;
Surprise, surprise... The getMonth() method returns the month in the range 0..11.
Answer from Kelly works to me
Just changed this
if(month<9) month = "0"+(month+1);
if(date<10) day = "0"+date;