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

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

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

Issues getting the number of weeks between two dates in javascript

This function of mine returns a massive amount of weeks that doesnt make sense
getWeeksToDate(){
var current_date = new Date();
console.log(current_date) //Sat Jan 11 2020 17:07:30 GMT+0100 (Central European Standard Time)
console.log(new Date(555555558555)); //Mon Aug 10 1987 02:59:18 GMT+0200 (Central European Summer Time) [I did set this randomly for the test]
var seconds_to_date = (new Date(current_date) -new Date(555555558555) )
var weeks_to_date = seconds_to_date/60/60/24/7;
console.log("semanas vividas:" +Math.ceil(weeks_to_date));
//Returns lived weeks to date rounded to upper number
return Math.ceil(weeks_to_date); //returns 1691805 weeks, which doesnt make sense since its around 32445 years, when it should equal to around 33 years
}
new Date(...) - new Date(...) returns the timestamp in milliseconds. Thus, you need to additionally divide by 1000 to convert the milliseconds into seconds.
var weeks_to_date = seconds_to_date/1000/60/60/24/7;

Unable to get the first day of the Month in Angular 2/4

I'm calculating the dates for my application like date,week,month.
First I am defining day,week,month,custom like:
this.reportTypes = [{TypeId: 1, Type: 'Day'}, {TypeId: 6, Type: 'Week'}, {TypeId: 30, Type: 'Month'}, {
TypeId: 10,
Type: 'Custom'
}]
Next I'm defining dates like:
var currdate = new Date();
if(reportType==1){
// this.reportDataFromDate=currdate;
// this.reportDataToDate=currdate;
//This is for setting the current date
this.reportDataFromDate= currdate;
this.reportDataToDate= currdate;
}
else if(reportType==30){
var First = new Date(currdate.getFullYear(),currdate.getMonth(),1);
this.reportDataFromDate=First;
this.reportDataToDate=currdate;
}
else if(reportType!=10){
var last = new Date(currdate.getTime() - (reportType * 24 * 60 * 60 * 1000));
this.reportDataFromDate=last;
this.reportDataToDate=currdate;
}
}
The problem is after selecting reportType == 30 then it has to get the first day of the month.
It is showing the date as 1-Dec-2017 but it is getting the data of till 30th November 2017?
This is screenshot of the SQL server. I'm sending the date as 1st Dec 2017 but it is getting 30-11-2017.
When the Date() constructor is invoked with integers, the result is a date object with that date assumed your systems (read browser/os) timezone.
Example:
let d = new Date(2017);
// returns Thu Jan 01 1970 01:00:02 GMT+0100 (W. Europe Standard Time)
// and with d.toUTCString(): Fri, 30 Dec 2016 23:00:00 GMT
Which may end up in an entire different year when sending to the server
Using the string constructor and specifying timezone will help you overcome this.
Example:
let d = new Date('2017z');
// returns Sun Jan 01 2017 01:00:00 GMT+0100 (W. Europe Standard Time)
// and with d.toUTCString(): Sun, 01 Jan 2017 00:00:00 GMT
The latter which is what you should pass to a server, and normally do calculations on.
However, note that calculations with dates are a complicated matter best left to a library like moment.js. To get a feel of what you are dealing with have a look at this great talk from the WebRebel conference.
So to actually give an answer to your title, try this example which creates the date in a simple string using UTC:
let d = new Date(currdate.getUTCFullYear() + ' ' +(currdate.getUTCMonth() + 1) + ' 1z');
d.getUTCDay(); // returns the day as an integer where Monday is 0.
Note that we add 1 month due to getUTCMonth() returns January as 0.
Why the difference?
The new Date(x,y,z) constructor treats the parameters as local date values.
See MDB Web Docs - Date
Note: Where Date is called as a constructor with more than one argument, the specifed arguments represent local time. If UTC is desired, use new Date(Date.UTC(...)) with the same arguments.
But, under the hood the date is stored as UTC (milliseconds since 1 Jan 1970).
const date = new Date(2017, 11, 29);
console.log('valueOf()', date.valueOf()) // 1514458800000
and the UTC date is different to your local date (see trailing 'Z' indicates UTC)
const date = new Date(2017, 11, 29);
console.log('date', date) // "2017-12-28T11:00:00.000Z" (trailing 'Z' means UTC)
// The difference in minutes between browser local and UTC
console.log('getTimezoneOffset()', date.getTimezoneOffset() )
and when you send it to the server, JSON sends it as UTC
const date = new Date(2017, 11, 29);
console.log('JSON', date.toJSON())
// JSON will yield string version of UTC === 2017-12-28T11:00:00.000Z
How to fix it
Well, you might decide that you actually want the date/time in local, and conclude it's not broken.
But if you want to send UTC to the server, wrap the parameters in Date.UTC()
const date = new Date(Date.UTC( 2017, 11, 29 ))
console.log('date.toJSON()', date.toJSON() ) // 2017-12-29T00:00:00.000Z
What about month parameter === 11?
From the MDB page referenced above,
Note: The argument month is 0-based. This means that January = 0 and December = 11.
If you are using .Net Web API as backend, you can config the timezone in Web API WebApiconfig.cs like below. It will serialize the time in UTC.
public static void Register(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
}
Or use
config.Formatters.JsonFormatter.SerializerSettings.DateTimeZ‌​oneHandling = Newtonsoft.Json.DateTimeZoneHandling.RoundtripKind; //Time zone information should be preserved when converting.

Compare dates issue - javascript

I need to compare dates in javascript.
After attempt many ways...
I choose:
var endDate = new Date(secondDate.getYear(), secondDate.getMonth(), secondDate.getDate(), 0, 0, 0,0);
var startDate = new Date(firstDate.getYear(), firstDate.getMonth(), firstDate.getDate(), 0, 0, 0, 0);
if (endDate.getTime() >= startDate.getTime()) {
isValid = true;
}
else {
isValid = false;
}
In my situation:
---startDate = Tue Apr 01 1997 00:00:00 GMT+0200 (Jerusalem Standard Time) (i.e, 01/04/1997)
---endDate = Thu Jul 26 114 00:00:00 GMT+0200 (Jerusalem Standard Time) (i.e, 26/07/2014)
You see? startDate is small then endDate, right?
But:
---endDate.getTime() returns: -58551904800000
---startTime.getTime() returns: 859845600000
so, endDate.getTime() >= startDate.getTime() returns false...
In other situation, it works well:
---startDate: Sat Jul 21 114 00:00:00 GMT+0200 (Jerusalem Standard Time) (i.e, 21/07/2014)
---endDate: Sat Jul 28 114 00:00:00 GMT+0200 (Jerusalem Standard Time) (i.e, 28/07/2014)
---startDate.getTime() returns -58552336800000
---endDate.getTime() returns -58551732000000
so, endDate.getTime() >= startDate.getTime() returns true...
It seems like that javascript functions have another behavior for dates after year 2000.
What should I do? which code will be match to all of the optional situations?
Thanks.
Yeah like ghusse said, there is a problem with your end time if you fixed it so it was 2014 you would get a result such as 1406329200000 instead of -58551904800000
I found a solution, after I read Josh and ghusse answers and advice:
Use getFullYear(), instead getYear(), and all will work O.K.
Apparently, you have a problem with your end dates :
Thu Jul 26 114 00:00:00 GMT+0200
Does not mean 21/07/2014 but 21/07/114
According to the doc, here are 2 correct ways of creating your date:
var endDate = new Date(21, 6, 2014);
// Or a string corresponding to a version of ISO8601
var endDate = new Date('2014-07-21T00:00:00z+3');

Overriding the Javascript Date constructor?

I am developing a browser application that is sensitive to the current date.
Throughout my application's code, I call new Date and perform calculations based on the current time and render the view accordingly.
In order to test my application for different potential calendar days, I would have to constantly change my system clock to the past or future, which is an annoyance and probably not healthy for my computer.
So purely for testing purposes (I would never use this code in production), I decided to override the built-in Date constructor by doing this in the console:
// create a date object for this Friday:
var d = new Date(2012, 0, 20)
//override Date constructor so all newly constructed dates return this Friday
Date = function(){return d}
With this assumption in mind, I tried this and got strange results:
var now = new Date
Sat Apr 07 2012 00:00:00 GMT-0400 (EDT)
now = new Date
Tue Jul 10 2012 00:00:00 GMT-0400 (EDT)
now = new Date
Wed Jul 09 2014 00:00:00 GMT-0400 (EDT)
now = new Date
Wed Jun 07 2023 00:00:00 GMT-0400 (EDT)
...and so on....
My question is, what exactly is going on here?
If I overrode the constructor to return a static date, why does it give unrelated and constantly incrementing dates?
Also, is there an effective way I can override the Date constructor to return a static date in the future without having to go through all date instantiation calls in my code and modifying the output?
Thanks in advance.
EDIT:
I tried my code in a fresh window and it worked as expected.
It seems the culprit was the jQuery UI datepicker plugin which was calling its "refresh" method. When I disable its call, the date overriding works normally, but as soon as I use the datepicker, the strange behavior above occurs.
No idea why this popular plugin would somehow affect something global like this. If anyone has any ideas, let me know.
Sorry for not figuring out the true culprit earlier.
I also faced this problem and ended up writing a module for that. Perhaps it's useful for somebody:
Github: https://github.com/schickling/timemachine
timemachine.config({
dateString: 'December 25, 1991 13:12:59'
});
console.log(new Date()); // December 25, 1991 13:12:59
I tested your code:
// create a date object for this Friday:
var d = new Date(2012, 0, 20);
//override Date constructor so all newly constructed dates return this Friday
Date = function(){return d;};
var now = new Date()
console.log(now);
now = new Date()
console.log(now);
now = new Date()
console.log(now);
now = new Date()
console.log(now);
And the result ???? Why so different?
Date {Fri Jan 20 2012 00:00:00 GMT+0700 (SE Asia Standard Time)}
Date {Fri Jan 20 2012 00:00:00 GMT+0700 (SE Asia Standard Time)}
Date {Fri Jan 20 2012 00:00:00 GMT+0700 (SE Asia Standard Time)}
Date {Fri Jan 20 2012 00:00:00 GMT+0700 (SE Asia Standard Time)}
EDIT:
I saw that whenever you interact with the Date Picker, the behavior goes different. Try another test, change the now is something like interact with Date Picker:
// create a date object for this Friday:
var d = new Date(2012, 0, 20);
//override Date constructor so all newly constructed dates return this Friday
Date = function(){return d;};
var now = new Date();
var another = new Date();
console.log(now);
another.setDate(13);
now = new Date()
console.log(now);
And the result is:
Date {Fri Jan 20 2012 00:00:00 GMT+0700 (SE Asia Standard Time)}
Date {Fri Jan 13 2012 00:00:00 GMT+0700 (SE Asia Standard Time)}
So, what goes wrong?
You already overridden core Date function by
Date = function(){return d;}; // after construction, all date will be d (2012-01-20)
var now = new Date(); // you instantiate a date, but actually now variable is d (2012-01-20)
var another = new Date(); // you instantiate a date, but another is still d (2012-01-20)
another.setDate(13); // change another date to 13 is to change now to 13 (because now and another is still one d)
now = new Date() // still d
console.log(now); // print out now (2012-01-13)
So, you overrides core Date function by a function that causes all date use the same (just one) instance, which is d (2012-01-20). Change any dates affect others.
This is working for me.
I.E how to return process time 1 minute back
Date = class extends Date{
constructor(options) {
if (options) {
super(options);
} else {
super(Date.now() - 1000 * 60);
}
}
};
Give this a shot.
var d = new Date(2012, 0, 20);
// undefine date so that it will only return what your function returns
Date = undefined;
Date = function(){return d;}
Modifying the prototype to point to your object should do the trick.
I believe the strange behavior you were experiencing earlier was that privately Date holds some notion of time, and since the prototype points to that internal clock, you were getting random times.
Alex Stanovsky's answer almost did it for me but this modification made the constructor work like before when given parameters.
Date = class extends Date {
constructor(...options) {
if (options.length) {
super(...options);
} else {
super(2019, 2, 11, 19, 19);
}
}
};
I used the below to enforce UTC dates
var _f = function(item) {
Date.prototype["get" + item] = Date.prototype["getUTC" + item];
Date.prototype["set" + item] = Date.prototype["setUTC" + item];
}
var _d = ['Milliseconds', 'Seconds', 'Minutes', 'Hours', 'Date', 'Month', 'FullYear', 'Year', 'Day'];
_d.forEach(_f);
Date = class extends Date {
constructor(...options) {
if (options.length == 1 && options[0].constructor == Date) {
super(options[0]);
} else if (options.length > 0) {
super(Date.UTC(...options));
} else {
super(Date.UTC());
}
}
};

Categories

Resources