【问题标题】:JS date functions show different date on different browsersJS日期函数在不同的浏览器上显示不同的日期
【发布时间】:2022-01-26 02:53:19
【问题描述】:

我们有一个日期格式化功能,它似乎会根据浏览器生成不同的日期。该函数有两个步骤,首先确定用户的日期格式,然后相应地格式化日期。

// determine date string format for PrettyDate functions
var dtstr;
var dtsep;
let customDate = new Date(2222, 11, 18);
let strDate = customDate.toLocaleDateString();
let daTyp = strDate.substring(0, 2);
if (daTyp === '22') {
  dtstr = 'YMD';
  dtsep = ',';
}
else if (daTyp === '12') {
  dtstr = 'MDY';
  dtsep = ';';
}
else {
  dtstr = 'DMY';
  dtsep = ',';
}

// make dates human readable
function prettyDate(datestr, use) {
  var date = new Date(datestr);
  if (!isNaN(date.getTime())) {
    const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    const monthCount = date.getMonth();
    const theMonth = monthNames[monthCount];
    const theYear = date.getFullYear();
    const theDay = date.getDate();
    if (use === 'short') {
      if (dtstr === 'MDY') {
        return theMonth + ' ' + theDay;
      }
      else {
        return theDay + ' ' + theMonth;
      }
    }
    else {
      if (dtstr === 'YMD') {
        return datestr;
      }
      else if (dtstr === 'MDY') {
        return theMonth + ' ' + theDay + ', ' + theYear;
      }
      else {
        return theDay + ' ' + theMonth + ' ' + theYear;
          }
    }
  }
}

被转换的datestr 的格式为 2022-08-17,use 的值是“短”或“长”。

我们在可以访问的计算机上进行的所有检查都显示结束日期为 2022 年 8 月 17 日或 2022 年 8 月 17 日。但我们有几个网站用户报告他们得到的是 2022 年 8 月 16 日或 2022 年 8 月 16 日。

更新

已尝试使用计算机时区进行一些实验,但似乎确实有影响。那么新的紧迫问题是我们如何修改代码以防止操作系统时区影响结果?

对计算机时区设置的进一步试验表明,如果时区为 UTC +XX:00,则显示的日期是正确的。如果是 UTC -XX:00,则日期提前一天。

终于

我正式授予自己当天的 Dunderhead 奖。我的datestr 基本上是一个字符串,所以只需使用split() 并改造部分。多么设计过度的菜鸟之举。

function prettyDate(datestr, use) {
  const dtparts = String(datestr).split('-');
  const monthNames = ["","Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  const monthCount = +dtparts[1];
  const theMonth = monthNames[monthCount];
  const theYear = dtparts[0];
  const theDay = dtparts[2];
  ... previous code
}

感谢那些试图提供帮助的人。

【问题讨论】:

  • 你确定这与你同时测试的机器的时区没有任何关系吗?
  • @esqew - 时区将如何影响 JS? datestr 值来自我们服务器上的数据库。
  • 您使用的是同一个浏览器吗?看到这个帖子:stackoverflow.com/questions/3552461/…
  • @code - 我已经成功尝试了多个浏览器。一位报告该问题的网站访问者在 Win 11 上尝试了几种浏览器,Edge 显示了正确的日期,Firefox 显示了错误的日期,Win10 上的 Edge 显示了错误的日期。这是一个树桩..
  • 不确定它是否与datestr 格式有关,但请尝试将它们格式化为2022/08/17 而不是使用连字符-,因为这在某些浏览器中似乎存在一些解析问题:dygraphs.com/date-formats.html

标签: javascript date


【解决方案1】:

如果初始日期字符串的格式为“YYYY-MM-DD”,则 if 解析使用:

new Date(datestr)

它将被解析为 UTC,因此任何具有负偏移量的人(即格林威治以西)的日期都将是前一天。这个问题在Why does Date.parse give incorrect results?

此外,尝试确定 toLocaleString 的格式然后模仿该格式似乎不是一个好主意。只需将 toLocaleString 与合适的选项一起使用,这就是它应该使用的方式。但是,您无法确定将呈现给用户的格式,因为它依赖于实现(并假设用户已适当地设置了他们的浏览器或系统语言)。

如果日期字符串应该被解析为本地,那么在重新格式化的过程中手动进行,例如

// Parse timestamp in YYYY-MM-DD format as local
// and format as unambiguous timestamp with short month name
function reformatTimestamp(s, lang = 'default') {

  // Parse timestamp as local
  let [y, m, d] = s.split(/\D/);

  // Fromat with short month name so unambiguous
  return new Date(y, m-1, d).toLocaleString(lang, {
    year:'numeric', month:'short', day:'numeric'});
}

// Results for different languages:
//   en-GB : 22 Jan 2022
//   en-US : Jan 222, 2022
//   fr    : 22 janv. 2022
//   ar    : ٢٢ يناير، ٢٠٢٢
console.log(reformatTimestamp('2022-01-22'));

上面有一个可选的语言参数,即BCP47 language tag)(通常被错误地称为“语言环境”)。

【讨论】:

  • 感谢 date() 解析为 UTC 的澄清,这解释了它。我们真的不想全力以赴进行国际化,因为该网站只有英文版。我们只是想安排熟悉的 D M Y 序列。
  • 简单地使用明确的格式就足够了,例如2022 年 1 月 22 日和 2022 年 1 月 22 日都不会被误解。人们喜欢对日期格式大惊小怪,但实际上这是一个小问题。例如。 en-GB 应该是 d/m/y,但 The Times newspaper,这是你能得到的英国机构,使用“2022 年 1 月 27 日星期四”,并且已经使用了几个世纪(337 年而且还在继续……)。跨度>
  • RobG 是的,这只是一个小问题,但有时正是这些小事帮助人们从旁观者变成了预订者(它适用于旅游网站 :)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-22
  • 2015-03-19
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
相关资源
最近更新 更多