Let value changes out of nowhere - javascript

Can someone please explain to me, why start and end variables print to console different values for these loggers?
I get printed out:
start1 = Mon Feb 17 2020 10:00:00 GMT+0100 (Central European Standard Time)
end1 = Mon Feb 17 2020 11:30:00 GMT+0100 (Central European Standard Time)
start2 = Mon Feb 17 2020 11:30:00 GMT+0100 (Central European Standard Time)
end2 = Mon Feb 17 2020 11:30:00 GMT+0100 (Central European Standard Time)
I want to add, that the code I presented is in some method of course, and the names start and end don't interfere with other variable names.
let start = this.service.getDateTime(
eventFromUi.start_date,
eventFromUi.start_time_hour,
eventFromUi.start_time_minute
);
console.log("start1 = " + start);
let end = this.service.getDateTime(
eventFromUi.start_date,
eventFromUi.end_time_hour,
eventFromUi.end_time_minute
);
console.log("end1 = " + end);
console.log("start2 = " + start);
console.log("end2 = " + end);
EDIT:
The getDateTime() method returns object of TypeScript ootb type Date.
I used Chrome debugger to look into this, and I see that when I first execute the getDateTime() method, I get value Mon Feb 17 2020 10:00:00 GMT+0100 (Central European Standard Time) returned and assigned to let start.
Then the method getDateTime() is executed again and retuns value Mon Feb 17 2020 11:30:00 GMT+0100 (Central European Standard Time), and this value gets assigned to both start and end variables.
How does this happen?
EDIT2:
Function getDateTime:
getDateTime(dateWithoutTime: Date, hour: number, minute: number): Date {
let date = dateWithoutTime;
console.log(date);
console.log(hour);
console.log(minute);
date.setHours(hour);
date.setMinutes(minute);
return date;
}

This is happening because you're dealing with object references.
getDateTime(dateWithoutTime: Date, hour: number, minute: number): Date {
let date = dateWithoutTime;
// date is now a copy of the *reference* to the same object that
// dateWithoutTime is a reference to. In other words: it is pointing
// to the same object in memory
date.setHours(hour);
date.setMinutes(minute);
// since date is pointing to the same object as dateWithoutTime, this is
// modifying both date and dateWithoutTime
return date;
}
This also means that in your code, eventFromUi.start_date, start and end are all references pointing to the same Date object.
To solve your problem, make sure you create a clone of dateWithoutTime when it is passed into your function:
getDateTime(dateWithoutTime: Date, hour: number, minute: number): Date {
let date = new Date(dateWithoutTime);
// date is now a reference to a *new Date object* with the same
// date/time/etc. values as dateWithoutTime
date.setHours(hour);
date.setMinutes(minute);
// since date now points to a new object, this is only modifying date
// while leaving dateWithoutTime alone and unchanged
return date;
}

Related

Why do this dates not match?

i have this code which works with dates:
let startDate = new Date(toolOrder.jsAppStartDate.getTime()); // clone date
startDate.setDate(startDate.getDate() - Math.floor((days - 1) / 2)); // sub some days
console.log(toolOrder.jsAppStartDate); // Output: Date Thu Sep 21 2023 00:00:00 GMT+0200 (Central European Summer Time)
console.log(toolOrder.jsAppStartDate.getTime()); // Output: 1695247200000
console.log("--------------");
for (let index = 0; index < days; index++)
{
console.log(startDate);
console.log(startDate.getTime());
// ... some drawing code here ...
startDate.setDate(startDate.getDate() + 1); // add one day
if(startDate === toolOrder.jsAppStartDate) // check if start date reached
{
console.log("Dates match");
startDate = new Date(toolOrder.jsAppEndDate.getTime());
}
}
The output of the log before the loop is:
Date Thu Sep 21 2023 00:00:00 GMT+0200 (Central European Summer Time)
1695247200000
---------------
The output from the loop is:
Date Mon Sep 18 2023 00:00:00 GMT+0200 (Central European Summer Time)
1694988000000
Date Tue Sep 19 2023 00:00:00 GMT+0200 (Central European Summer Time)
1695074400000
Date Wed Sep 20 2023 00:00:00 GMT+0200 (Central European Summer Time)
1695160800000
Date Thu Sep 21 2023 00:00:00 GMT+0200 (Central European Summer Time)
1695247200000
Date Fri Sep 22 2023 00:00:00 GMT+0200 (Central European Summer Time)
1695333600000
So even if the dates match in loop 3, the if condition is not true. It works when I use
if(startDate.getTime() === toolOrder.jsAppStartDate.getTime())
but I thought it should work without also?
=== compares identity so:
startDate === toolOrder.jsAppStartDate
Means: is startDate the same object [in memory] as toolOrder.jsAppStartDate which is not the case because toolOrder.jsAppStartDate is a different object and not the object referred to by the name startDate.
mdn says this about the strict equality operator:
If both operands are objects, return true only if they refer to the same object.
(emphasis mine)
if(startDate.getTime() === toolOrder.jsAppStartDate.getTime())
Works because you're now comparing numbers instead of objects.
The rule for the two operands being numbers is:
Otherwise, compare the two operand's values:
Numbers must have the same numeric values. +0 and -0 are considered to be the same value.
mdn (emphasis mine)
You are comparing Date instances with each other when you're using the === operator. However, they are not the same instance. Each new Date creates a unique, new instance (unless the class constructor deliberately returns a previously created instance [for more info: singleton pattern]).
When you are comparing each instance's getTime() result, you are comparing 2 primitive values (numbers in this case). Primitive values are not class instances; so === works like == with primitives.

How to create function that return a Date object?

1 - Make a function that given a date in text format "dd/mm/yyyy" returns a Date object with that date, using the Split() method.
2 - You have to do a "console.log() of the Date object created" and it should output something similar to
Mon Dec 2 2019 11:36:25 GMT+0100 (Central European Standard Time).
I have tried this but I don't know why when I write a console.log
I get the following:
2022-12-05T00:00:00.000Z
And I try to get it to appear something like this:
Mon Dec 2 2019 12:30:05 GMT+0100 (Central European Standard Time)
function convertDate(date) {
let dateArray = date.split("/");
let DateString = dateArray[2] + "/" + dateArray[1] + "/" + dateArray[0] + "Z";
let dateDate = new Date(dateString);
return dateDate;
}
console.log(convertDate("05/12/2022"));
you can use new Date() to get the date like "Wed Dec 28 2022 11:36:25 GMT+0100"
let date = new Date("05/12/2022");
console.log(date);
output will be Thu May 12 2022 00:00:00 GMT+0500 (Pakistan Standard Time) {}

Javascript Date comparison coming from server and new Date()

I have a date coming from database which is 2022-10-31 11:33:07.861Z, and in my js file I have this date is saved in a variable :
function test() {
let now = new Date().toLocaleString('en-GB', { timeZone: 'Europe/London'}); // I need now to be Europe/london time
let dateFromDb = db_date; // 2022-10-31 11:33:07.861Z
// I have a function which takes ^ above date and returns this : Mon Oct 31 2022 11:33:07 GMT+0000 (Greenwich Mean Time)
let formatedDate= this.toDate(dateFomDb); // returns : Mon Oct 31 2022 11:33:07 GMT+0000 (Greenwich Mean Time)
}
When I console.log(now, typeOf now) I get this: 02/11/2022, 23:24:52 string
and console for formatedDate returns this : Mon Oct 31 2022 11:33:07 GMT+0000 Object
I need to compare both dates :
return newDate <= now; // expect it to true or false;
Can anyone please suggest me how can I do this ?
I tried to cast both dates toLocalString but its string from I need object.

What type of date strings are these in JS?

I get a date string as Fri Sep 17 2021 11:50:59 GMT-0400 (Eastern Daylight Time) from one place. I get it from 2021-09-17T11:50:59-04:00 in a second place.
I want to convert the first format to the second.
I am doing this in a crazy way, so I am thinking there must be a better one.
var d = new Date(`Fri Sep 17 2021 11:50:59 GMT-0400 (Eastern Daylight Time)`);
var iso = d.toISOString();
var time = d.toTimeString();
console.log(iso);
console.log(time);
var [date] = iso.split('T')
var [,localTime, timezone] = time.match(/([^ ]+) GMT([^ ]+)/);
var timezoneWithColon = timezone.replace(/(-*[0-9]{2,2})([0-9]{2,2})/,"$1:$2")
var desiredFormat = '2021-09-17T11:50:59-04:00';
var convertedFormat = `${date}T${localTime}${timezoneWithColon}`;
console.log(desiredFormat)
console.log(convertedFormat)
console.log(desiredFormat === convertedFormat);
The fiddle is over at https://jsfiddle.net/Dave_Stein/8tLv2g4j/.
2021-09-17T11:50:59-04:00 is an ISO-8601 date string.
toISOString should work, however it will convert the time to UTC. If you want this to format in your current timezone, you'll have to use a library such as date-fns:
import { formatISO } from 'date-fns'
formatISO(new Date(`Fri Sep 17 2021 11:50:59 GMT-0400 (Eastern Daylight Time)`))
// prints '2021-09-17T11:50:59-04:00'

Convert Javascript Date object to other timezone Date Object

How to convert Javascript Date Object to another timezone but the result must be Date object with the correct timezone
let date = new Date();
console.log(date);
date = date.toLocaleString('en-US', { timeZone: 'America/Vancouver' });
date = new Date(date);
console.log(date);
that gives the following result, the last result line (Date/Time) is correct but the time zone is incorrect which is still GMT-0500 (Colombia Standard Time) but must be GMT-0800 (Pacific Standard Time) timezone
Wed Jan 20 2021 00:14:11 GMT-0500 (Colombia Standard Time)
Tue Jan 19 2021 21:14:11 GMT-0500 (Colombia Standard Time)
You may try this :
let date = new Date();
console.log(date);
date = date.toLocaleString("en-CA", {
timeZone: "America/Vancouver",
timeZoneName: "long",
});
console.log(date);
Output:
Wed Jan 20 2021 09:18:16 GMT+0300 (Arabian Standard Time)
2021-01-19, 10:18:16 p.m. Pacific Standard Time
Once you get the correct TimeZone, you may change how the date and time are displayed by string manipulation if you need too.
Update:
This may not look pretty but i believe it should satisfy the requirements:
let date = new Date().toLocaleString("en-US", {
timeZone: "America/Vancouver",
timeZoneName: "short",
});
let date1 = new Date(date);
//adding a new property to Date object called tz and initializing it to null
Date.prototype.tz = null;
//stting the tz value to the Time zone output from toLocalString
date1.tz = date.slice(date.length - 3);
console.log(date1.toISOString() + " " + date1.tz);
console.log(date);
console.log(typeof date1);
Output:
2021-01-20T09:01:06.000Z PST
1/20/2021, 1:01:06 AM PST
Object
What i've done is create a new property of the object date to replace the built-in time zone property in Date, hence you get an object with a user specified Time zone.

Categories