I offer same day shipping if the user places an order before 9AM ET. If they place the order after 9AM, same day shipping is unavailable.
My server is using UTC time so I need to check if the time is greater than or less than 9AM ET regardless of the time where the user is located.
Not being an expert with JS, I cobbled together this code.
var d = new Date();
var e = d.getHours().toLocaleString('en-US', { timeZone: 'America/New_York' });
var f = '';
if(e >= 9) {
f = 'shipping unavailable';
}
else {
f = 'shipping available';
}
I am getting the correct result after 9AM ET on my computer but I am concerned that same day shipping will be offered after 9AM ET.
2 Answers 2
Your code has a bug: d.getHours()
will return a plain number. Calling toLocaleString
on that number calls Number.prototype.toLocaleString
, which:
returns a string with a language-sensitive representation of this number.
It does not do anything with timezones; the second parameter does not recognize a timeZone
property. For example, where I am now, .getHours()
returns 9
, and (9).toLocaleString('en-US', { timeZone: 'America/New_York' })
returns "9"
.
On your server, to retrieve the hours in a particular timezone, one method would be to call toLocaleString
on the date object itself with the appropriate timezone, then extract the number of hours from that string:
const timeString = new Date().toLocaleString('en-US', { timeZone: 'America/New_York' });
const [, hours, ampm] = timeString.match(/ (\d+).* ([AP]M)/);
console.log('In NY, it is:', hours, ampm);
Other issues:
- Since it's 2020, best to prefer at least 2015+ syntax, which should not be an issue since the code is running on the server. (Among other things, being able to use
const
is wonderful) - You initialize
f
to the empty string, but then you reassign it immediately; the empty string is not used, so there's no point to assigning it. - Or, even better: since you want to conditionally assign a value to
f
depending on the number of hours, it would be more appropriate (and shorter) to use the conditional operator:
const f = Number(hours) < 9 && ampm === 'AM'
? 'shipping available'
: 'shipping unavailable';
-
\$\begingroup\$ Thanks a lot for the detailed reply. After applying the code changes it appears to work as desired. There's still a lot to learn. \$\endgroup\$Junky– Junky2020年09月01日 14:37:57 +00:00Commented Sep 1, 2020 at 14:37
-
\$\begingroup\$ I have a question related to javascript dates, for operations like calculus of current date minus one day or some other similar operations there is some specific library usually used (maybe
moment.js
) ? Thanks for your attention. \$\endgroup\$dariosicily– dariosicily2020年09月01日 16:56:01 +00:00Commented Sep 1, 2020 at 16:56 -
1\$\begingroup\$ @dariosicily Yes, I believe moment.js is the most popular JS date library used by far. You can also subtract days very easily with the built-in Date too. \$\endgroup\$CertainPerformance– CertainPerformance2020年09月01日 17:25:39 +00:00Commented Sep 1, 2020 at 17:25
From a short review;
Naming could be better for when you look back at the code;
var d
could beconst now
var e
could beconst hour
var f
could belet shippingLabel
toLocaleString
does not do what you want with time zonesAs a beginner, I would not go for ternary to keep things ultra simple
So my counter proposal would be
const now = new Date();
const hour = now.getHours();
let shippingLabel;
if(hour >= 9) {
shippingLabel = 'Shipping unavailable';
} else {
shippingLabel = 'Shipping available';
}
-
\$\begingroup\$ Thanks for your replay but getHours returns the hour, according to local time. I need the hour to always be compared to ET. \$\endgroup\$Junky– Junky2020年09月01日 14:35:58 +00:00Commented Sep 1, 2020 at 14:35
-
1\$\begingroup\$ For that, I would strongly suggest to use moment.js, momentjs.com/timezone \$\endgroup\$konijn– konijn2020年09月01日 14:37:06 +00:00Commented Sep 1, 2020 at 14:37