Check if ISO String date is between two dates - javascript

I want to check if the middle date is between the right and left date, how can I accomplish this in Javascript, they are an ISO String.
From 2021-01-30T05:00:00.000Z <-> Date 2021-01-31T22:18:46Z <-> To 2021-01-31T05:00:00.000Z
How can I verify 2021-01-31T22:18:46Z is between 2021-01-30T05:00:00.000Z and 2021-01-31T05:00:00.000Z

Two easy options...
Compare the date strings lexicographically
const From = "2021-01-30T05:00:00.000Z"
const date = "2021-01-31T22:18:46Z"
const To = "2021-01-31T05:00:00.000Z"
if (From.localeCompare(date) <= 0 && To.localeCompare(date) >= 0) {
console.log("Date is in range")
} else {
console.log("Date is not in range")
}
or parse the date strings as Date instances or timestamps and compare them numerically
const From = new Date("2021-01-30T05:00:00.000Z")
const date = new Date("2021-01-31T22:18:46Z")
const To = new Date("2021-01-31T05:00:00.000Z")
if (From <= date && To >= date) {
console.log("Date is in range")
} else {
console.log("Date is not in range")
}
Note: If you're using Typescript, it doesn't like comparing Date instances numerically. Compare Date.prototype.valueOf() or Date.prototype.getTime() instead

The main idea is we just need to compare Date only.
However, if you use .moment or new Date() to parse the date-time UTC, you will recognize an interesting that
moment("2021-01-31T22:18:46Z").format("YYYY-MM-DD") // "2021-02-01"
new Date("2021-01-31T22:18:46Z") // Mon Feb 01 2021 05:18:46 GMT+0700 (Indochina Time)
So if the compareDate like 2021-01-31T05:00:00.000Z, then you will get the expected result.
const fromDate = moment("2021-01-30T05:00:00.000Z").format("YYYY-MM-DD");
const conpareDate = moment("2021-01-31T05:00:00.000Z").format("YYYY-MM-DD");
const toDate = moment("2021-01-31T05:00:00.000Z").format("YYYY-MM-DD");
console.log({fromDate, conpareDate, toDate});
console.log(moment(conpareDate).isBetween(fromDate, toDate, undefined, '(]'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
If you still want to compare exactly the date, you can achieve it in this way (But to be honest, It's not recommended).
const fromDate = '2021-01-30T05:00:00.000Z'.split('-');
const conpareDate = '2021-01-31T22:18:46Z'.split('-');
const toDate = '2021-01-31T05:00:00.000Z'.split('-');
const partStringToInt = (str) => parseInt(str, 10);
const compareBetween = (a, b, c) => partStringToInt(a) <= partStringToInt(b) && partStringToInt(b) <= partStringToInt(c);
const result = compareBetween(fromDate[0], conpareDate[0], toDate[0]) // Year
&& compareBetween(fromDate[1], conpareDate[1], toDate[1]) // Month
&& compareBetween(fromDate[2].substring(0, 2), conpareDate[2].substring(0, 2), toDate[2].substring(0, 2)); // Day
console.log(result);

function getElapsedMS(strOfD1, strOfD2) {
var d1 = new Date(strOfD1);
var d2 = new Date(strOfD2);
return d1-d2;
}
var d2d1 = getElapsedMS("2021-01-31T22:18:46Z", "2021-01-30T05:00:00.000Z");
var d2d3 = getElapsedMS("2021-01-31T22:18:46Z", "2021-01-31T05:00:00.000Z");
if (d2d1 * d2d3 < 0) { // can have more consideration to avoid overflow
//d2 is between d1 and d3
}

Unix timestamp
Each date can be represented as milliseconds since epoch, so we can convert each date to milliseconds and compare whether one date is after another or not.
Example:
const dateA = new Date("2021-01-30T05:00:00.000Z");
const dateB = new Date("2021-01-31T05:00:00.000Z");
const dateC = new Date("2021-01-31T22:18:46Z");
// We use getTime() method to get the date as milliseconds since epoch
const isDateCBetweenAandB = dateA.getTime() <= dateC.getTime() && dateC.getTime() <= dateB.getTime();
console.log(isDateCBetweenAandB);

You can compare its unix timestamp try it:
Date.parse('2021-01-31T22:18:46Z');

Related

how to get the most recent dates from array of dates in javascript?

Here I am receiving the array of dates like this from the API,
let dates = ["22/1/2022","22/7/2022","9/10/2018"]
From these dates, I need to get the most recent date i.e 22/07/2022.
I got the below example from a site, This code works correctly only if the date matches the format of YYYY/MM/DD.
CODE
function max_date(all_dates) {
var max_dt = all_dates[0],
max_dtObj = new Date(all_dates[0]);
all_dates.forEach(function (dt, index) {
if (new Date(dt) > max_dtObj) {
max_dt = dt;
max_dtObj = new Date(dt);
}
});
return max_dt;
}
console.log(max_date(["2015/02/01", "2022/02/02", "2023/01/03"]));
Can we use some packages like date-fns or momentjs . to get the desired result despite the date format (or) with JS itself its achievable?
Please let me know your solution for this.
With date-fns you can do it like
import { max, parse } from "date-fns"
const dates = ["22/1/2022","22/7/2022","9/10/2018"];
console.log(max(dates.map((d) => parse(d, "d/M/yyyy", new Date()))))
// returns Fri Jul 22 2022 00:00:00 GMT+0200 (Central European Summer Time)
You can use pure Javascript for the logic
Convert strings to dates
Use timestamps (by getTime()) to find max
Convert that max timestamp back to date or string
const dates = ["22/1/2022", "22/7/2022", "9/10/2018"]
const convertStringToDate = (dateString) => {
const [day, month, year] = dateString.split("/");
return new Date(year, month - 1, day);
}
function format(inputDate) {
let date, month, year;
date = inputDate.getDate();
month = inputDate.getMonth() + 1;
year = inputDate.getFullYear();
return `${date}/${month}/${year}`;
}
const timestamps = dates.map(date => convertStringToDate(date).getTime())
const max = Math.max(...timestamps)
console.log(format(new Date(max)))
Sorting in descending order and returning the first element will do the work.
let dates = ['22/1/2022', '22/7/2022', '9/10/2018'];
const latestDate = (dates) => {
dates.sort((a, b) => {
const date1 = new Date(a.split('/').reverse().join('-'));
const date2 = new Date(b.split('/').reverse().join('-'));
return date2 - date1;
});
// First el will be latest date
return dates[0];
};
console.log(latestDate(dates));
// Output: 22/7/2022

Get timezone from date string in JavaScript

I'm working on a function that should check if a given dateString has the same timeZone as the browser timeZone. To get the browser timeZone I can use either a) Intl.DateTimeFormat().resolvedOptions().timeZone which will return Europe/Amsterdam for example or b) new Date().getTimeZoneOffset() that will return -60. Both are fine.
The tricky part is to get the timeZone from the dateString I want to pass, for example from: 2021-01-01T00:00:00-05:00 (which should be America/New_York or 300 AFAIK). How can I get the timeZone from that date? I tried to do: new Date('2021-01-01T00:00:00-05:00').getTimeZoneOffset() but that will convert it to the timeZone of my browser again, returning -60.
Example of function:
function isSameTimeZone(date) {
// function to get time zone here
const a = getTimeZone(date)
return a === new Date().getTimeZoneOffset() || Intl.DateTimeFormat().resolvedOptions().timeZone
}
Testcases
2021-01-01T00:00:00-08:00 (SF)
2021-01-01T00:00:00-05:00 (NY)
2021-01-01T00:00:00+05:30 (Mumbai)
2021-01-01T00:00:00+01:00 (Amsterdam)
Anyone out there with a solution? Thanks in advance!
Here's my method;
function checkTimezone(dateString) {
const testDate = new Date(dateString);
const dateRegex = /\d{4}-\d{2}-\d{2}/;
const myDate = new Date(testDate.toISOString().match(dateRegex)[0]);
return !(testDate - myDate);
}
const testCases = ['2021-01-01T00:00:00-05:00', '2021-01-01T00:00:00-08:00', '2021-01-01T00:00:00-05:00', '2021-01-01T00:00:00+05:30', '2021-01-01T00:00:00+01:00'];
testCases.forEach(testCase => console.log(checkTimezone(testCase)));
So here's how it works, you pass in your date string and create a new Date() instance with it.
Then I get the ISO string with the Date.ISOString() method and match it with the original string to get the date and create another Date instance from it without the time.
Then I find the difference (comes in milliseconds), and convert it to minutes
So I've been testing around a bit and in the end I came up with the following solution, based on the dates I provided in my question.
const getTimeZoneOffsetFromDate = date => {
/*
Check if the offset is positive or negative
e.g. +01:00 (Amsterdam) or -05:00 (New York)
*/
if (date.includes('+')) {
// Get the timezone hours
const timezone = date.split('+')[1]
// Get the hours
const hours = timezone.split(':')[0]
// Get the minutes (e.g. Mumbai has +05:30)
const minutes = timezone.split(':')[1]
/*
Amsterdam:
const offset = 01 * -60 = -60 + -0 = -60
*/
const offset = hours * -60 + parseInt(-minutes)
return offset === new Date().getTimezoneOffset()
}
// Repeat
const timezone = date.slice(date.length - 5)
const hours = timezone.split(':')[0]
const minutes = timezone.split(':')[1]
/*
New York:
const offset = 05 * 60 = 300 + 0 = 300
*/
const offset = hours * 60 + parseInt(minutes)
return offset === new Date().getTimezoneOffset()
}
console.log(getTimeZoneOffsetFromDate('2021-01-01T00:00:00+01:00'))

Date validation and relative delta between two dates in javascript

I have an interface where I receive a date in this format: Month/Year, ex: 11/2022.
I would like to verify that this is a valid date.
I use the datatables editor. The configuration (see below) of the field works well, but since the user can enter the date himself without going through the calendar, there is a risk that the date entered is incorrect. It doesn't work like an input mask. So i need to validate the date in the code.
{
type: "datetime",
label: "Date:",
name: "Date",
def: function () { return new Date(); },
format: 'MM/YYYY',
fieldInfo: 'Format: Month/Year (ex: 12/2022)',
keyInput: true
}
The date should not be accepted if the difference between this date and today's date is less than 3 months.
It means that, compared to today, all dates before July will have to be rejected.
Currently I can do this with the relativedelta method of the python dateutil module. But as the validation must be done on the client side, I would like to do this in javascript (which I know very little).
The example below shows how to do this. You should take advantage of the HTML 5 input types to validate your dates. You also need to calculate 3 months from now in myEpoch and then compare it to the date/time given
HTML:
<p>
Date & Time: <input id="foo" type="datetime-local" />
</p>
JavaScript:
var myEpoch = new Date();
myEpoch.setMonth(myEpoch.getMonth() + 3);
myEpoch = myEpoch.getTime();
var foo = document.getElementById("foo");
if (foo.value < myEpoch) {
//show a message saying this date is invalid
}
Since user is entering date in MM/yyyy format, so i'm assuming that you take 1 as a date into account, i.e., if input is 03/2020, you would consider it as: 01/03/2020. Right? If
so, then you can do the following to validate this date:-
function isValidDate(inputDate) {
// Unfortunately JS doesn't have any in-built function to validate date in MM/yyyy format. Hence regex comes to the rescue
var regex = /^([0-9]{1,2})\/([0-9]{4,4})$/;
var matches = regex.exec(inputDate);
if (!matches || matches.length != 3) {
throw new Error('Please provide date in MM/yyyy format');
}
var inputMonth = matches[1]; // Return month from input date
var inputYear = matches[2]; // Return year from input date
var finalDate = inputMonth+ '/01/' + inputYear;
// Check if entered date is valid or not
var parsedDate = Date.parse(finalDate);
if (isNaN(parsedDate)) {
throw new Error('Unable to parse date.');
}
// Check if it is less than 3 months or not.
var isValid = !isLessThan3Months(new Date(finalDate), new Date());
return isValid;
}
function isLessThan3Months(dateToCompare, currentDate) {
var diffYears = currentDate.getFullYear() - dateToCompare.getFullYear();
var diffMonths = currentDate.getMonth() - dateToCompare.getMonth();
var diffDays = currentDate.getDate() - dateToCompare.getDate();
var months = diffYears * 12 + diffMonths;
if (diffDays > 0) {
months += '.' + diffDays;
} else if (diffDays < 0) {
months--;
months +=
'.' +
(new Date(currentDate.getFullYear(), currentDate.getMonth(), 0).getDate() + diffDays);
}
return months < 3;
}
isValidDate('03/2020');
So now, by calling isValidDate with user's input date in MM/yyyy format, you should be able to check if it is valid or not.
For this, you won't need to use any third party javascript library. Just plain javascript is enough.
You should probably use Moment.js, because working with the raw Date object is fiddly.
If you would rather use plain JavaScript, then the following might be of use:
const moreThan3MonthsHence = ({ utcYear, utcMonth },
now = new Date,
target = new Date(Date.UTC(utcYear, utcMonth)),
threeMonthsHence = addMonths(new Date(now.valueOf()), 3)) =>
(target > threeMonthsHence)
const validate = (str,
[utcMonth, utcYear] = str.split('/'),
date = new Date(Date.UTC(+utcYear, (+utcMonth)-1))) =>
moreThan3MonthsHence({ utcYear: date.getUTCFullYear(), utcMonth: date.getUTCMonth() })
const addMonths = (date, months, d = date.getDate()) => {
date.setMonth(date.getMonth() + +months);
// If rolled over to next month, set to last day of previous month
if (date.getDate() != d) {
date.setDate(0);
}
return date;
}
// Note: input is one-based months
console.log(validate('07/2020')) // true
console.log(validate('06/2020')) // false
console.log(validate('12/2019')) // false
Notes
now is internally represented as the milliseconds since the Unix epoch. Note this includes the current time of day.
target is the milliseconds since the Unix epoch of midnight on the supplied UTC date.
threeMonthsHence is the milliseconds since the Unix epoch of now (including time of day), plus three months.
validate parses the input string.
addMonths is necessary because the built-in function can roll-over into a new month with unexpected behavior.
Finally to solve my problem I mixed the solutions proposed by #Sumit Parakh and #ControlAltDel.
function isValidDate(inputDate) {
var regex = /^([0-9]{1,2})\/([0-9]{4,4})$/;
var matches = regex.exec(inputDate);
var parsedDate = 0;
if (!matches || matches.length != 3) {
throw new Error('Please provide date in MM/yyyy format');
}
else {
var inputMonth = matches[1]; // Return month from input date
var inputYear = matches[2]; // Return year from input date
var finalDate = inputMonth+ '/01/' + inputYear;
// Check if entered date is valid or not
var parsedDate = Date.parse(finalDate);
if (isNaN(parsedDate)) {
parsedDate = 0;
//throw new Error('Unable to parse date.');
}
return parsedDate;
}
var myEpoch = new Date();
myEpoch.setMonth(myEpoch.getMonth() + 3);
myEpoch = myEpoch.getTime();
finalDate = isValidDate(date_peremption.val());
if (finalDate == 0){
date_received.error("This date is invalid");
}
else if(finalDate < myEpoch) {
date_received.error("The date must be more than three months last");
}
It's not very elegant, but it works. Thanks everyone

how compare two dates with moment.js

I have three different types of dates and I can not compare them.
let withOneDayLess = moment().subtract(1, "days").format("DD-MM-YYYY");
//let justnow = moment().format("DD-MM-YYYY");
let takenAt = moment.unix(story.takenAt).format("DD-MM-YYYY");
if(takenAt >= withOneDayLess){
Arrstory.push(story)
console.log(takenAt," - " ,withOneDayLess)
};
story.takenAt is the date of a story in unix, and I need all the stories between yesterday and today, but I think the if compares only the first number, giving me stories that do not correspond
I'm assuming your currentDate variable is also created as a .format("DD-MM-YYYY") method call... so you're not comparing dates - you're comparing strings. Compare the dates to get your desired result:
var d1 = moment().subtract(1,"days");
var d2 = moment();
if (d1 < d2) alert(d1);
let currentDate = moment();
let story = { takenAt: 1746713004 };
let withOneDayLess = moment().subtract(1, "days").format("DD-MM-YYYY");
let justnow = moment().format("DD-MM-YYYY");
let takenAt = moment.unix(story.takenAt).format("DD-MM-YYYY");
// this will never alert - typeof(takenAt) === "string" and the comparison
// "08-05-2025" is not >= "Sat Jan 05 2019 10:36:11 GMT-0800" as currentDate
// get coerced to a string to do the comparison if it's not a string already.
if(takenAt >= currentDate){
alert("takenAt is later than currentDate");
}
// this WILL work because it's comparing a moment date to a moment date directly.
takenAt = moment.unix(story.takenAt);
if(takenAt >= currentDate){
alert(takenAt.format("DD-MM-YYYY") + " is later than " + currentDate.format("DD-MM-YYYY"));
}

How to check if date is in this week in javascript?

I have this date "2016-04-23T11:45:00Z" and I want to check this date in this week or not ?
Thanks,
Dates are hard, I would always suggest using a library dedicated to date handling as it reduces the chances of errors in your code.
MomentJS is a good one.
var now = moment();
var input = moment("2016-04-17T11:45:00Z");
var isThisWeek = (now.isoWeek() == input.isoWeek())
Edit: Please note as of 2020 moment may not be a good choice for new projects
This seems to be working for me.
function isDateInThisWeek(date) {
const todayObj = new Date();
const todayDate = todayObj.getDate();
const todayDay = todayObj.getDay();
// get first date of week
const firstDayOfWeek = new Date(todayObj.setDate(todayDate - todayDay));
// get last date of week
const lastDayOfWeek = new Date(firstDayOfWeek);
lastDayOfWeek.setDate(lastDayOfWeek.getDate() + 6);
// if date is equal or within the first and last dates of the week
return date >= firstDayOfWeek && date <= lastDayOfWeek;
}
const date = new Date();
const isInWeek = isDateInThisWeek(date);
<div ng-app="myApp">
<div class="container" ng-controller="Ctrl_List">
<h1>{{currentDate}}</h1>
<h1>{{numberCurrentDateWeeks}}</h1>
<h1>{{yourDate}}</h1>
<h1>{{numberYourDateWeeks}}</h1>
</div>
</div>
......
angular.module('myApp', [])
.controller("Ctrl_List", ["$scope", "$filter", function(s, $filter) {
s.yourDate = '2016-04-23T11:45:00Z'
s.currentDate = new Date();
s.numberCurrentDateWeeks = $filter('date')(s.currentDate, "w");
s.numberYourDateWeeks = $filter('date')(s.yourDate, "w");
}]);
then you got the Week numbers just compare or do whatever you like
cheers !
You can do that without any libraries by checking if the date.getTime() (milliseconds since epoch) is between last monday and next monday:
const WEEK_LENGTH = 604800000;
function onCurrentWeek(date) {
var lastMonday = new Date(); // Creating new date object for today
lastMonday.setDate(lastMonday.getDate() - (lastMonday.getDay()-1)); // Setting date to last monday
lastMonday.setHours(0,0,0,0); // Setting Hour to 00:00:00:00
const res = lastMonday.getTime() <= date.getTime() &&
date.getTime() < ( lastMonday.getTime() + WEEK_LENGTH);
return res; // true / false
}
(one week in ms = 24 * 60 * 60 * 1000 * 7 = 604,800,000)
May not be the most optimal solution, but I think it's quite readable:
function isThisWeek (date) {
const now = new Date();
const weekDay = (now.getDay() + 6) % 7; // Make sure Sunday is 6, not 0
const monthDay = now.getDate();
const mondayThisWeek = monthDay - weekDay;
const startOfThisWeek = new Date(+now);
startOfThisWeek.setDate(mondayThisWeek);
startOfThisWeek.setHours(0, 0, 0, 0);
const startOfNextWeek = new Date(+startOfThisWeek);
startOfNextWeek.setDate(mondayThisWeek + 7);
return date >= startOfThisWeek && date < startOfNextWeek;
}
This link explaines, how to do this without using any js libraries. https://gist.github.com/dblock/1081513
Code against link death:
function( d ) {
// Create a copy of this date object
var target = new Date(d.valueOf());
// ISO week date weeks start on monday
// so correct the day number
var dayNr = (d.getDay() + 6) % 7;
// Set the target to the thursday of this week so the
// target date is in the right year
target.setDate(target.getDate() - dayNr + 3);
// ISO 8601 states that week 1 is the week
// with january 4th in it
var jan4 = new Date(target.getFullYear(), 0, 4);
// Number of days between target date and january 4th
var dayDiff = (target - jan4) / 86400000;
// Calculate week number: Week 1 (january 4th) plus the
// number of weeks between target date and january 4th
var weekNr = 1 + Math.ceil(dayDiff / 7);
return weekNr;
}
I managed to do it with this simple trick and without any external library.
Considering monday as the first day of the week, the function takes as parameter a date string and do the validation before checking if the day indeed is in the current week.
function isInThisWeek(livr){
const WEEK = new Date()
// convert delivery date to Date instance
const DATEREF = new Date(livr)
// Check if date instance is in valid format (depends on the function arg)
if(DATEREF instanceof Date && isNaN(DATEREF)){
console.log("invalid date format")
return false}
// Deconstruct to get separated date infos
const [dayR, monthR, yearR] = [DATEREF.getDate(), DATEREF.getMonth(), DATEREF.getFullYear()]
// get Monday date
const monday = (WEEK.getDate() - WEEK.getDay()) + 1
// get Saturday date
const sunday = monday + 6
// Start verification
if (yearR !== WEEK.getFullYear()) { console.log("WRONG YEAR"); return false }
if (monthR !== WEEK.getMonth()) { console.log("WRONG MONTH"); return false }
if(dayR >= monday && dayR <= sunday) { return true }
else {console.log("WRONG DAY"); return false}
}
In the comments I saw that you stated that your week starts on Monday.
In that case, I guess it'd be a good idea to calculate the ISO week number of the 2 dates and see if you get the same week number for both of them.
To calculate the ISO week number, check this answer:
In case anyone else's week starts on Sunday instead, you can use this answer to calculate the week number accordingly.
then you can do something like this:
function isSameWeek(date1, date2) {
return date1.getWeekNumber() === date2.getWeekNumber();
}
const isDateInThisWeek = (date) => {
const today = new Date();
//Get the first day of the current week (Sunday)
const firstDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay())
);
//Get the last day of the current week (Saturday)
const lastDayOfWeek = new Date(
today.setDate(today.getDate() - today.getDay() + 6)
);
//check if my value is between a minimum date and a maximum date
if (date >= firstDayOfWeek && date <= lastDayOfWeek) {
return true;
} else {
return false;
}
};

Categories

Resources