javascript - 使用 jQuery Datepicker 的英国夏令时(计算丢失 1 天)

标签 javascript datetime jquery-ui-datepicker

我使用 Vue.js with jQuery Datepicker并查看计算所选日期还剩多少天的问题: enter image description here

计算天数差异:

getDifferenceInDays: function(date1, date2) {
  const diffTime = date2.getTime() - date1.getTime(); //Math.abs(...);
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  return diffDays;
},

结果我看不到 13 天了。也许这个问题与 10 月 27 日结束的英国夏令时有关: British Summer Time ends on 27th October

您能否提出解决此问题的任何想法。 非常感谢!

最佳答案

没错,这是由夏令时 (DST) 过渡引起的,特别是英国的夏令时将于 10 月 27 日结束。

日期、时间和时区在 JavaScript 中真的很棘手。当我们访问不同的时区时, native Date 对象很难处理。

我建议检查一个在这种事情上做得更好的库:momentmoment-timezone非常擅长正确处理 DST 更改。

您得到错误结果的原因是您正在查看 UTC 时区中日期之间的差异(因为 getTime() 始终返回自 1970-01-01 00:00 UTC 以来的毫秒数( Unix 纪元))。

结果(在您的情况下)将是 13.04(或 13 + 1/24)天,因为 UTC 偏移量在两个日期(从 UTC+01 到 UTC+00)之间发生变化。

例如,伦敦时间 10 月 14 日 12:00 为 11:00 UTC, 而伦敦时间 10 月 27 日 12:00 是世界标准时间 12:00。所以差异将是 313 小时,或 13.04 天。

由于您正在调用 Math.ceil,这将四舍五入为 14,这是不正确的。

这适用于两个日期都在相同的 UTC 偏移量内(例如,都在夏季,都在冬季)。但是如果它们是 DST 更改的任一侧,您将得到不正确的结果。

下面的代码将计算指定时区中两个日期之间的天数。您可以将 true 的第三个参数传递给 moment.diff 以获取小数天数。 (在这种情况下将为 0)。

如果您不想使用其他库(例如 moment),您可以简单地使用 Math.round 来获取大致的天数差异。这不会那么稳健,因为如果 date2 比 date1 早不到 12 小时,您将获得零天差。 只要您了解这一点,它就可以满足您的需求。我添加了一个 getDifferenceInDaysRounding 来显示这一点。

const CURRENT_TIMEZONE = "Europe/London";

// Date 1 is 12:00, 14th October, London time
const date1 = moment.tz("2019-10-14T12:00:00", CURRENT_TIMEZONE).toDate();

// Date 2 is 12:00, 27th October, London time
const date2 = moment.tz("2019-10-27T12:00:00", CURRENT_TIMEZONE).toDate();

function getDifferenceInDaysOriginal (date1, date2) {
  const diffTime = date2.getTime() - date1.getTime();
  let diff1 = diffTime / (1000 * 60 * 60 * 24);
  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
  return diffDays;
}

// Use with caution.. this will not work in all cases!
function getDifferenceInDaysRounding (date1, date2) {
  const diffTime = date2.getTime() - date1.getTime();
  const diffDays = Math.round(diffTime / (1000 * 60 * 60 * 24));
  return diffDays;
}

function getDifferenceInDaysTimezoneAware(date1, date2, timezone) {
  // Ensure the dates are in the correct timezone.
  const dateLocal1 = moment.tz(date1.getTime(), timezone);
  const dateLocal2 = moment.tz(date2.getTime(), timezone);

  // Pass false to return the integer number of days. NB, this will be 0 for less than 24 hours difference. Pass true to get the fractional days.
  return dateLocal2.diff(dateLocal1, "days", false);
}

console.log("Original result:", getDifferenceInDaysOriginal(date1, date2));
console.log("Get difference (rounding):", getDifferenceInDaysRounding(date1, date2));
console.log("Timezone-aware result:", getDifferenceInDaysTimezoneAware(date1, date2, CURRENT_TIMEZONE));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://momentjs.com/downloads/moment-timezone-with-data-1970-2030.js"></script>

关于javascript - 使用 jQuery Datepicker 的英国夏令时(计算丢失 1 天),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58374831/

相关文章:

javascript - 如何在javascript中制作基于下拉列表的查询mysql?

javascript - 与 Material UI 表分页 react 显示所有条目

JavaScript 将字母数组转换为数字

java - Joda Time - 将 UTC 日期时间转换为日期 - 使用 Joda 版本 1.2.1.1

javascript - 在事件上调用两个函数

javascript - 循环javascript中的所有元素进行解析?

mysql - 为什么 1401-01-01 在 Ruby 中是星期六而在 MySQL 中是星期四?

date - 如果 golang 中的条件出错

php - 在日期选择器上设置值

javascript - Jquery datepicker 和多个选择事件