Compare dates in Day.js? - javascript

How do I check if 'Tue Jan 31 2023 00:00:00 GMT+0100' is the same day and month as '2023-01-31T18:45:00-06:00'?
It's very confusing.
let dates = [
{slot: '2023-01-31T18:45:00-06:00'}
{slot: '2023-01-31T19:00:00-06:00'}
{slot: '2023-01-31T19:15:00-06:00'}
{slot: '2023-01-31T19:30:00-06:00'}
{slot: '2023-01-31T19:45:00-06:00'}
{slot: '2023-01-31T20:00:00-06:00'}
]
let dayjsDate = dayjs('Tue Jan 31 2023 00:00:00 GMT+0100') // DateJS object!
dates.forEach(x => {
let oneSlot = dayjs(x.slot)
if (oneSlot.isSame(dayjsDate, 'day')
&& oneSlot.isSame(dayjsDate, 'month')) {
console.log("Yes")
} else {
console.log("No")
}
})

I'm not actually familiar with Day.js or momentjs (your 2 tags) but I believe you can do this in good old vanilla JS (meaning no packages necessary).
I'll preface this by saying I'm no expert in Dates in JS, so my approach might be a weird one.
I like to "normalize" dates without timezones, so I start with your source one that you called dayjsDate as
let source_date = "Tue Jan 31 2023 00:00:00 GMT+0100".split(' ');
source_date.pop();
source_date = new Date(source_date); //log would give "Tue Jan 31 2023 00:00:00 GMT-0500 (Eastern Standard Time)" since I'm in EST
(or if you want to do it in a single line:
let source_date = new Date("Tue Jan 31 2023 00:00:00 GMT+0100".split(' ').slice(0,-1)); )
Then, with the values in your array, since we only care about the date portions, I would do:
let dates = [ //directly from your post, but I added commas
{slot: '2023-01-31T18:45:00-06:00'},
{slot: '2023-01-31T19:00:00-06:00'},
{slot: '2023-01-31T19:15:00-06:00'},
{slot: '2023-01-31T19:30:00-06:00'},
{slot: '2023-01-31T19:45:00-06:00'},
{slot: '2023-01-31T20:00:00-06:00'},
];
let cleaned_dates = dates.map(x => new Date(x.slot.substring(0, 10) + 'T00:00:00')); //an array of dates
We can now easily compare the dates, by virtue of something like:
cleaned_dates.forEach(x => isSame(x, source_date));
function isSame(date_1, date_2) {
let same = (date_1.getMonth() === date_2.getMonth()) && (date_1.getDate() === date_2.getDate());
if (same) console.log('Same');
else console.log('Different');
return same;
}
If you would also like to compare by year, you can easily add another like as && date_1.getFullYear() === date_2.getFullYear(). These are native JS functions that work with Date objects.
Functions in JS are "hoisted" so they load before everything else, so they can be called before they are declared.

Related

How to compare timeStamp whe i can't seem to bring them to a common format using GAS?

So, on form submit, I got a timestamp, which looks like this:
"values":["2/18/2022 14:11:25"]
I then need to compare it with the one on the spreadsheet, so that I can set a number to an adjacent column.
Then, I'm using the code below, but I'm facing an error on ```Utilities.formatDate()````
The code:
function onSubmit(e) {
Logger.log("%s", JSON.stringify(e));
const timeStamp = e.values[0]
const formRespSheet = e.source.getSheetByName('Form Responses 1')
var maxNumber = Math.max.apply(null, formRespSheet.getRange(2, 14, formRespSheet.getLastRow(), 1).getValues());
maxNumber = maxNumber + 1
Utilities.sleep(1000);//Tried it
const allTimeStamps = formRespSheet.getRange(2, 1, formRespSheet.getLastRow(), 1).getValues();
for (let a = 0; a < allTimeStamps.length; a++) {
let sheetTimeStamp = allTimeStamps[a]
sheetTimeStamp = Utilities.formatDate(sheetTimeStamp, Session.getTimeZone(), "MM/dd/yyyy HH:mm:ss")
if (sheetTimeStamp.valueOf() == timeStamp.valueOf()) {
const row = a + 1
formRespSheet.getRange(row, 14).setValue(maxNumber)
}
}
}
The error says:
The parameters (number[],String,String) don't match the method signature for Utilities.formatDate.
Thanks for your help.
Google Spreadsheet has a Date object that works very well for comparion. I always, and don't understand why everyone doesn't, set the number format of a cell or cells to Date. That way I can compare dates, subtract dates, etc. etc. Now, I know the time interers but a simple function can alleviate that problem, I have a spreadsheet that has two Dates that have the same date but they have different times. So I can compare if they are the same day.
function test() {
try {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
var range = sheet.getRange("B1:B2");
var values = range.getValues();
function removeTime( value ) {
var temp = value[0];
value[0] = new Date(temp.getFullYear(),temp.getMonth(),temp.getDate());
};
console.log( new Date(values[0][0]) );
console.log( new Date(values[1][0]) );
console.log(values[0][0].valueOf() === values[1][0].valueOf());
values.forEach( removeTime );
console.log( new Date(values[0][0]) );
console.log( new Date(values[1][0]) );
console.log(values[0][0].valueOf() === values[1][0].valueOf());
}
catch(err) {
console.log(err);
}
}
9:15:47 AM Notice Execution started
9:15:47 AM Info Fri Feb 18 2022 11:53:45 GMT-0500 (Eastern Standard Time)
9:15:47 AM Info Fri Feb 18 2022 11:54:16 GMT-0500 (Eastern Standard Time)
9:15:47 AM Info false
9:15:47 AM Info Fri Feb 18 2022 00:00:00 GMT-0500 (Eastern Standard Time)
9:15:47 AM Info Fri Feb 18 2022 00:00:00 GMT-0500 (Eastern Standard Time)
9:15:47 AM Info true
9:15:48 AM Notice Execution completed
sheetTimeStamp = Utilities.formatDate(sheetTimeStamp, Session.getTimeZone(), "MM/dd/yyyy HH:mm:ss")
change into:
sheetTimeStamp = Utilities.formatDate(new Date(sheetTimeStamp), Session.getTimeZone(), "MM/dd/yyyy HH:mm:ss")
it should work

Are references to Date object inside a map function carried over?

I am running into a weird issue where the dates in a function I have are being written to objects (and then stored) are having some side effects.
const normalizedEntries = allEntries.map((item) => {
const dateObj = new Date(item.timestamp * 1000);
const groupedDate = new Date(item.timestamp * 1000);
groupedDate.setHours(0, 0, 0, 0);
console.log(dateObj);
console.log(groupedDate);
const normalizedEntry: NormalizedEntry = {
sites: item.sites,
date: dateObj.toISOString(),
groupedDate: groupedDate.toISOString(),
};
console.log(normalizedEntry);
return normalizedEntry;
});
All I am trying to do in this function is take in an object that has a timestamp and a number (the sites field) and produce this new typed object NormalizedEntry which you can see has the original date, the sites (number) and a grouped date (which is just the day but with the time set to zero so I can group multiple objects later in redux).
Within the first two passes of the loop (for now I am working with a small set - 300, of test data) the data begins to get out of whack and I don't understand why. Is there something going on with the references of the dates? Or perhaps something about dates I do not understand yet? Below is the output of those console logs from above
// iteration one
Wed Jan 20 2021 17:16:49 GMT-0500 (Eastern Standard Time)
Wed Jan 20 2021 00:00:00 GMT-0500 (Eastern Standard Time)
{sites: 26, date: "2021-01-20T22:16:49.000Z", groupedDate: "2021-01-20T05:00:00.000Z"}
// iteration two
Wed Jan 20 2021 20:27:58 GMT-0500 (Eastern Standard Time)
Wed Jan 20 2021 00:00:00 GMT-0500 (Eastern Standard Time)
{sites: 41, date: "2021-01-21T01:27:58.000Z", groupedDate: "2021-01-20T05:00:00.000Z"}
As you can see the console.log(dadte) prints out the correct thing in the second iteration but for some reason when setting it to the object below it says it's on the 21st versus the 20th which it clearly is 5 lines above. This is in turn throwing all of my data out of whack.
EDIT:
Now trying to resolve it being a timezone issue as pointed out from below but this is still not resolving the issue:
const normalizedEntries = allEntries.map((item, idx) => {
let originDate = new Date(item.timestamp * 1000);
const timezoneDifference = originDate.getTimezoneOffset() / 60;
const correctedDate = new Date(
originDate.setHours(originDate.getHours() + timezoneDifference, 0, 0, 0)
);
let groupedDate = correctedDate;
groupedDate.setHours(0, 0, 0, 0);
console.log(originDate.toString());
console.log(groupedDate.toString());
const normalizedEntry: NormalizedAcquisition = {
sites: item.sites,
date: originDate.toISOString(),
groupedDate: groupedDate.toISOString(),
};
return normalizedEntry;
});
The issue is the timezone
The dates have gmt -5
You set hours to 0 in that timezone
When you format as iso it uses gmt
You need to get the timezone and take into account when setting the time to 00:00
See mdn date.getTimezoneOffset

moment.js, list days based on locale dow

I have a script that is setting the day to start the week in the locale, however when I list out the days they arent in order that I expect:
moment.updateLocale(this.language, {
week: {
dow: 4,
},
});
const weekDays = moment.weekdaysMin();
In this scenario I would expect to get the list:
Thu Fri Sat Sun Mon Tue Wed
But I always get:
Sun Mon Tue Wed Thu Fri Sat
I would really appreciate some assistance as I can't figure out what is wrong here.
You can pass boolean argument to weekdaysMin to get weekdays sorted by locale.
See Listing the months and weekdays of the current Moment.js locale section of the docs:
Similarly, moment.monthsShort returns abbreviated month names, and moment.weekdays, moment.weekdaysShort, moment.weekdaysMin return lists of weekdays.
...
As of 2.13.0 you can pass a bool as the first parameter of the weekday functions. If true, the weekdays will be returned in locale specific order.
Here a live sample:
moment.updateLocale('en', {
week: {
dow: 4,
},
});
const weekDays = moment.weekdaysMin();
console.log(weekDays);
const weekDaysSort = moment.weekdaysMin(true);
console.log(weekDaysSort);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>

Figuring out why Date.parse() does not equal comparison date

When I compare arriveDate1 to holiday they are not equal and I'm not sure why. In the console both dates appear the same. Any ideas why this might be? (using Date.js).
var orderShip1 = Date.today(); //date it ships
var arriveDate1 = orderShip1.addDays(3); //first day it could arrive
var holiday = Date.parse('8/8/2014');
console.log(arriveDate1); // Fri Aug 08 2014 00:00:00 GMT-0400 (EDT)
console.log(holiday); // Fri Aug 08 2014 00:00:00 GMT-0400 (EDT)
if (arriveDate1 === holiday) {
orderShip1.addDays(1);
//arriveDate1 = orderShip1.addDays(1);
}
This happens because when you check with the == and === operators, Javascript performs a check by reference. This two objects, unless they are declared like holiday = arriveDate1, will then never be equal, because they don't share the same memory reference.
Example:
a = {foo: 'hello'};
b = {foo: 'hello'};
a == b;
> false
You should perform the check using .toISOString or the unary operator + to convert the data objects in milliseconds, like this:
// this
if (arriveDate1.toISOString() == holiday.toISOString()) ...
// or this
if (+arriveDate1 == +holiday) ...
The triple equals sign tests if objects are identical, that is they are the same object. Try double equals.

How to compare two dates (MonthName YearNumber) in javascript

This functionality is working fine in Chrome... But not IE or FF.
I am trying to validate two fields that take the value of MonthName YearNumber (see screenshot).
I am using Date.parse() to get miliseconds, then compare if Start Date <= End Date.
function IsStartEndDtError(StartDt, EndDt) {
//convert dates to miliseconds to compare if one is greater than other
var StartDtMili = Date.parse(StartDt);
var EndDtMili = Date.parse(EndDt);
if (StartDtMili <= EndDtMili) {
return false;
}
else {
return true;
}
}
What appears in Firebug:
Since the format your date is in isn't universally supported you can try a library like Date.js:
Date.parse("November 2012")
// returns: Thu Nov 01 2012 00:00:00 GMT+0000 (GMT)
If you don't want another library you can manually replace the month names with numbers and create a new date string.
Ecmascript does not seem to support full month names, if you look at "Section 15.9.1.15 Date Time String Format" in the spec.
In Firefox:
new Date("November 2012")
// Invalid Date
new Date("2012-11")
// Thu Nov 01 2012 00:00:00 GMT+0000 (GMT)
The second date format should be standardized across browsers, the first isn't.
11 1999, November 1999 are not parsable formats. You either need to use a date library that is more flexible with its input formats, or process your input and identify the parts in it:
function IsStartEndDtError(StartDt, EndDt) {
var months = {
January: 0,
February: 1,
...
};
//convert dates to miliseconds to compare if one is greater than other
var StartDtMili = (new Date(StartDt.split(" ")[1], month[StartDt.split(" ")[0]])).getTime();
var EndDtMili = (new Date(EndDt.split(" ")[1], month[EndDt.split(" ")[0]])).getTime();
if (StartDtMili <= EndDtMili) {
return false;
}
else {
return true;
}
}

Categories

Resources