如何使用 javascript 中的时区检查打开到关闭时间是否已过
How to check if open to close time has elapse using timezone in javascript
我在我的网络应用程序中有以下功能,使用国家/地区时区检查从 OPEN
到 CLOSE
的时间是否已经过去,并且工作正常。我正在尝试优化我的网站,所以我的问题是如何在不使用时刻时区的情况下在 javascript 中实现这样的功能?时区文件很大,这是我网站上的唯一用法。
function isOpen(openTime, closeTime, timezone) {
// handle special case
if (openTime === "24HR") {
return "open";
}
// get the current date and time in the given time zone
const now = moment.tz(timezone);
// Get the exact open and close times on that date in the given time zone
const date = now.format("YYYY-MM-DD");
const storeOpenTime = moment.tz(date + ' ' + openTime, "YYYY-MM-DD h:mmA", timezone);
const storeCloseTime = moment.tz(date + ' ' + closeTime, "YYYY-MM-DD h:mmA", timezone);
let check;
if (storeCloseTime.isBefore(storeOpenTime)) {
// Handle ranges that span over midnight
check = now.isAfter(storeOpenTime) || now.isBefore(storeCloseTime);
} else {
// Normal range check using an inclusive start time and exclusive end time
check = now.isBetween(storeOpenTime, storeCloseTime, null, '[)');
}
return check ? "open" : "closed";
}
const zone = "Asia/Kuala_Lumpur";
console.log("24HR", isOpen("24HR", undefined, zone));
console.log("2:00AM-8:00AM", isOpen("2:00AM", "8:00AM", zone));
console.log("8:00AM-10:00AM", isOpen("8:00AM", "10:00PM", zone));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.27/moment-timezone-with-data-10-year-range.min.js"></script>
您可以使用 Intl.DateTimeFormat constructor 来做同样的事情。据我了解,您想知道从 8:00 到 12:00 的商店是否正在营业,例如 Asia/Kuala_Lumpur 当前是否营业。
可能可以或多或少地逐行转换您的代码,但我只是重构了它并简化了逻辑(叫我懒惰......)。通过这种方式,它可以获取所需位置的当前时间,将其转换为自午夜以来的分钟数,然后查看它是在开始时间之前还是在结束时间之后。
对于午夜 (12:00 AM),时间转换为 0 分钟,因此如果 closingTime 为 0,则假定为一天结束,因此设置为 1,440 (即一天结束时的午夜)。
测试时间只在同一天有效,如果开放时间超过午夜则需要重构它。我刚刚测试了午夜到中午和中午到午夜,所以一个应该总是显示 "open" 而另一个 "closed".
您也可以考虑使用 Luxon,它的作用与 moment.js + moment.tz 相同,但使用 Intl 对象而不是包含的数据。
编辑
要处理超过午夜的时间,您可以在时间中包含日期(如果您想使用固定的每日时间表则不方便),或者您可以使用 "inside" 和 "outside" 测试,如果关闭时间早于打开时间,则测试时间是否在打开时间和关闭时间之间 而不是 。这可以通过比较 openMin 和 close 时间并调整测试来完成。
这不会处理重叠的开始和结束时间,但这并不真正适合常规的每日时间表(尽管它可能适合每周或更长的时间表)。
/* @param {string} location: IANA representative location
** @param {Date} date: date instance to get time from, default is now
** @returns {string} time in location in h:mm ap format
*/
function getTime(location, date = new Date()) {
return date.toLocaleString('en', {
timeZone: location,
hour : 'numeric',
minute: '2-digit',
dayPeriod: 'short'
});
}
/* @param {string} time: h:mm A
** @returns {number} time converted to minutes
*/
function timeToMin(time) {
let [h, m] = time.match(/\d\d?/g);
h = h%12;
if (/pm$/i.test(time)) h +=12
return h * 60 + parseInt(m);
}
/* @param {string} openTime: opening time in h:mm ap format
** @param {string} closeTime: closing time in h:mm ap format
** @param {string} location: IANA representative location
** @return {string} open if current time is within openTime and closeTime in location,
** closed otherwise
*/
function isOpen(openTime, closeTime, location) {
if (openTime == '24HR') return 'open';
let nowTime = getTime(location);
let nowMin = timeToMin(nowTime);
let openMin = timeToMin(openTime);
let closeMin = timeToMin(closeTime) || 1440;
// Open and close on same day
if (openMin < closeMin) {
return nowMin < openMin || nowMin >= closeMin ? 'closed' : 'open';
// Close on day after open
} else {
return nowMin >= openMin && nowMin < closeMin ? 'open' : 'closed';
}
}
// Time in KL
let loc = "Asia/Kuala_Lumpur";
console.log(`In ${loc} it's ${getTime(loc)}`);
// Examples
[["24HR", undefined, loc], // Open 24 hrs
["12:00AM", "12:00PM", loc], // Midnight to noon
["12:00PM", "12:00AM", loc], // Noon to midnight
["6:30PM", "04:00AM", loc], // Over midnight
].forEach(args => console.log(
`${args[0]}${args[1]? '-' + args[1] : ''} ${isOpen(...args)}`
));
我在我的网络应用程序中有以下功能,使用国家/地区时区检查从 OPEN
到 CLOSE
的时间是否已经过去,并且工作正常。我正在尝试优化我的网站,所以我的问题是如何在不使用时刻时区的情况下在 javascript 中实现这样的功能?时区文件很大,这是我网站上的唯一用法。
function isOpen(openTime, closeTime, timezone) {
// handle special case
if (openTime === "24HR") {
return "open";
}
// get the current date and time in the given time zone
const now = moment.tz(timezone);
// Get the exact open and close times on that date in the given time zone
const date = now.format("YYYY-MM-DD");
const storeOpenTime = moment.tz(date + ' ' + openTime, "YYYY-MM-DD h:mmA", timezone);
const storeCloseTime = moment.tz(date + ' ' + closeTime, "YYYY-MM-DD h:mmA", timezone);
let check;
if (storeCloseTime.isBefore(storeOpenTime)) {
// Handle ranges that span over midnight
check = now.isAfter(storeOpenTime) || now.isBefore(storeCloseTime);
} else {
// Normal range check using an inclusive start time and exclusive end time
check = now.isBetween(storeOpenTime, storeCloseTime, null, '[)');
}
return check ? "open" : "closed";
}
const zone = "Asia/Kuala_Lumpur";
console.log("24HR", isOpen("24HR", undefined, zone));
console.log("2:00AM-8:00AM", isOpen("2:00AM", "8:00AM", zone));
console.log("8:00AM-10:00AM", isOpen("8:00AM", "10:00PM", zone));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.27/moment-timezone-with-data-10-year-range.min.js"></script>
您可以使用 Intl.DateTimeFormat constructor 来做同样的事情。据我了解,您想知道从 8:00 到 12:00 的商店是否正在营业,例如 Asia/Kuala_Lumpur 当前是否营业。
可能可以或多或少地逐行转换您的代码,但我只是重构了它并简化了逻辑(叫我懒惰......)。通过这种方式,它可以获取所需位置的当前时间,将其转换为自午夜以来的分钟数,然后查看它是在开始时间之前还是在结束时间之后。
对于午夜 (12:00 AM),时间转换为 0 分钟,因此如果 closingTime 为 0,则假定为一天结束,因此设置为 1,440 (即一天结束时的午夜)。
测试时间只在同一天有效,如果开放时间超过午夜则需要重构它。我刚刚测试了午夜到中午和中午到午夜,所以一个应该总是显示 "open" 而另一个 "closed".
您也可以考虑使用 Luxon,它的作用与 moment.js + moment.tz 相同,但使用 Intl 对象而不是包含的数据。
编辑
要处理超过午夜的时间,您可以在时间中包含日期(如果您想使用固定的每日时间表则不方便),或者您可以使用 "inside" 和 "outside" 测试,如果关闭时间早于打开时间,则测试时间是否在打开时间和关闭时间之间 而不是 。这可以通过比较 openMin 和 close 时间并调整测试来完成。
这不会处理重叠的开始和结束时间,但这并不真正适合常规的每日时间表(尽管它可能适合每周或更长的时间表)。
/* @param {string} location: IANA representative location
** @param {Date} date: date instance to get time from, default is now
** @returns {string} time in location in h:mm ap format
*/
function getTime(location, date = new Date()) {
return date.toLocaleString('en', {
timeZone: location,
hour : 'numeric',
minute: '2-digit',
dayPeriod: 'short'
});
}
/* @param {string} time: h:mm A
** @returns {number} time converted to minutes
*/
function timeToMin(time) {
let [h, m] = time.match(/\d\d?/g);
h = h%12;
if (/pm$/i.test(time)) h +=12
return h * 60 + parseInt(m);
}
/* @param {string} openTime: opening time in h:mm ap format
** @param {string} closeTime: closing time in h:mm ap format
** @param {string} location: IANA representative location
** @return {string} open if current time is within openTime and closeTime in location,
** closed otherwise
*/
function isOpen(openTime, closeTime, location) {
if (openTime == '24HR') return 'open';
let nowTime = getTime(location);
let nowMin = timeToMin(nowTime);
let openMin = timeToMin(openTime);
let closeMin = timeToMin(closeTime) || 1440;
// Open and close on same day
if (openMin < closeMin) {
return nowMin < openMin || nowMin >= closeMin ? 'closed' : 'open';
// Close on day after open
} else {
return nowMin >= openMin && nowMin < closeMin ? 'open' : 'closed';
}
}
// Time in KL
let loc = "Asia/Kuala_Lumpur";
console.log(`In ${loc} it's ${getTime(loc)}`);
// Examples
[["24HR", undefined, loc], // Open 24 hrs
["12:00AM", "12:00PM", loc], // Midnight to noon
["12:00PM", "12:00AM", loc], // Noon to midnight
["6:30PM", "04:00AM", loc], // Over midnight
].forEach(args => console.log(
`${args[0]}${args[1]? '-' + args[1] : ''} ${isOpen(...args)}`
));