I am working on displaying a banner on a website, between two dates (the campaign's start date and end date).
For this purpose, I have the following function:
function checkCampaignActive() {
const campaignDateStart = new Date('2022-09-14');
const campaignDateStop = new Date('2022-09-15');
const today = Date.now();
const isCampaignStarted = today >= campaignDateStart.getTime();
const isCampaignExpired = today > campaignDateStop.getTime();
this.isCampaignActive = isCampaignStarted && !isCampaignExpired;
console.log('Is started: ', isCampaignStarted);
console.log('Is expired: ', isCampaignExpired);
console.log(isCampaignActive);
}
checkCampaignActive();
The problem
Since getTime()
returns the milliseconds between Jan 1 1970, 00:00 GMT and 2022-09-14 and 00:00 GMT and my local time is not GMT, there is a gap between the desired campaign start and the real one.
Whatever new Date('2022-09-14')
returns has to be adjusted for the local time, but remain an object, not a string.
What is the easiest way to fix this issue?
CodePudding user response:
The cause of the "problem" is that the date string your code provides to the Date
constructor is interpreted as a simplified ISO 8601 format, denoting UTC.
The best way is to avoid a string typed argument, and provide numeric arguments. The equivalent of your example would be:
const campaignDateStart = new Date(2022, 8, 14);
const campaignDateStop = new Date(2022, 8, 15);
(Be aware of the zero-based month numbering)
It is possible to get away with it using strings. For instance, these options work because they step away from the format that JavaScript will interpret as UTC:
Append a time specification (without appending "Z" or other time zone specifier);
const campaignDateStart = new Date('2022-09-14 00:00');
const campaignDateStop = new Date('2022-09-15 00:00');
As stated by Mozilla Contributors:
Date-only strings (e.g. "1970-01-01") are treated as UTC, while date-time strings (e.g. "1970-01-01T12:00") are treated as local.
Or use a different delimiter:
const campaignDateStart = new Date('2022/09/14');
const campaignDateStop = new Date('2022/09/15');
But these rely on the complex rules of how strings are parsed as dates. Some of that logic is host-dependent, so in general it is better to avoid passing strings to the date constructor (or to Date.parse
which uses the same logic for string arguments).
CodePudding user response:
A small change to your code will make it work the way you wish.
When you call new Date('2022-09-14') it returns the number of milliseconds from 1970-01-01 00:00:00 UTC to 2022-09-14 00:00:00 UTC, however you actually with to get the number of milliseconds from 1970-01-01 00:00:00 UTC 2022-09-14 00:00:00 [local timezone].
It's easy to make this change, simply parse '2022-09-14 00:00:00' instead, and the same with the subsequent date. This will return the expected values and give the correct answer.
function checkCampaignActive() {
const campaignDateStart = new Date('2022-09-14 00:00');
const campaignDateStop = new Date('2022-09-15 00:00');
const today = Date.now();
const isCampaignStarted = today >= campaignDateStart.getTime();
const isCampaignExpired = today > campaignDateStop.getTime();
this.isCampaignActive = isCampaignStarted && !isCampaignExpired;
console.log('Is started: ', isCampaignStarted);
console.log('Is expired: ', isCampaignExpired);
console.log(isCampaignActive);
}
checkCampaignActive();
.as-console-wrapper { max-height: 100% !important; }
CodePudding user response:
Visit this link: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTimezoneOffset
Add GMT in Date to add your timezone. Then use .getTimezoneOffset to get gap in Minutes.
function checkCampaignActive() {
const campaignDateStart = new Date('2022-09-14 GMT 5:45');
const campaignDateStop = new Date('2022-09-15 GMT 5:45');
const today = Date.now();
const today1 = Date.now() campaignDateStart.getTimezoneOffset() * 60;
const isCampaignStarted = today >= campaignDateStart.getTime();
const isCampaignExpired = today > campaignDateStop.getTime();
this.isCampaignActive = isCampaignStarted && !isCampaignExpired;
console.log('Is started: ', isCampaignStarted);
console.log('Is expired: ', isCampaignExpired);
console.log(isCampaignActive);
console.log(today);
console.log(today1);
console.log(campaignDateStart.getTimezoneOffset());
}
checkCampaignActive();