以用户的语言环境格式和时间偏移显示日期/时间

Posted

技术标签:

【中文标题】以用户的语言环境格式和时间偏移显示日期/时间【英文标题】:Display date/time in user's locale format and time offset 【发布时间】:2010-09-10 06:01:39 【问题描述】:

我希望服务器始终在 html 中提供 UTC 日期,并让客户端站点上的 javascript 将其转换为用户的本地时区。

如果我能以用户的语言环境日期格式输出,则奖励。

【问题讨论】:

【参考方案1】:

您可以使用 moment.js 来实现(2021 年弃用)

最好从 UTC 中parse 您的日期字符串如下(在服务器上创建一个ISO-8601 兼容字符串,以便在所有浏览器中获得一致的结果):

var m = moment("2013-02-08T09:30:26Z");

现在只需在您的应用程序中使用m,moment.js 默认使用本地时区进行显示操作。有many ways to format the date and time values 或提取部分内容。

您甚至可以像这样在用户区域设置中格式化时刻对象:

m.format('LLL') // Returns "February 8 2013 8:30 AM" on en-us

要将 moment.js 对象转换为不同的时区(即既不是本地时区也不是 UTC),您需要 moment.js timezone extension。该页面也有一些示例,使用起来非常简单。

注意:Moment JS 推荐更现代的替代方案,因此它可能不是新项目的好选择。

【讨论】:

你如何结合这一切? m.utcOffset(offset).format('LLL') 似乎不起作用。 现在应该 Luxon 或 Day.js 成为建议的库吗? 建议加For old projects, just use jQuery 在 chrome 上不起作用 - 即使在计算机的区域设置中时间设置为 24 小时,仍然显示上午/下午 momentjs 已宣布自己已弃用:momentjs.com/docs > 最近,Chrome 开发工具开始显示仅针对大小替换 Moment 的建议。我们普遍支持这一举措。【参考方案2】:

2021-可以使用浏览器原生Intl.DateTimeFormat

const utcDate = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));
console.log(new Intl.DateTimeFormat().format(utcDate));
// expected output: "21/04/2021", my locale is Switzerland

以下内容直接来自文档:

const date = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738));
// Results below assume UTC timezone - your results may vary

// Specify default date formatting for language (locale)
console.log(new Intl.DateTimeFormat('en-US').format(date));
// expected output: "12/20/2020"
    
// Specify default date formatting for language with a fallback language (in this case Indonesian)
console.log(new Intl.DateTimeFormat(['ban', 'id']).format(date));
// expected output: "20/12/2020"
    
// Specify date and time format using "style" options (i.e. full, long, medium, short)
console.log(new Intl.DateTimeFormat('en-GB',  dateStyle: 'full', timeStyle: 'long' ).format(date));
// Expected output "Sunday, 20 December 2020 at 14:23:16 GMT+11"

【讨论】:

【参考方案3】:

// new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
var serverDate = new Date(2018, 5, 30, 19, 13, 15); // just any date that comes from server
var serverDateStr = serverDate.toLocaleString("en-US", 
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
)
var userDate = new Date(serverDateStr + " UTC");
var locale = window.navigator.userLanguage || window.navigator.language;

var clientDateStr = userDate.toLocaleString(locale, 
  year: 'numeric',
  month: 'numeric',
  day: 'numeric'
);

var clientDateTimeStr = userDate.toLocaleString(locale, 
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
);

console.log("Server UTC date: " + serverDateStr);
console.log("User's local date: " + clientDateStr);
console.log("User's local date&time: " + clientDateTimeStr);

【讨论】:

供参考:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…(我的案例需要options 部分)【参考方案4】:

要将日期转换为本地日期,请使用 toLocaleDateString() 方法。

var date = (new Date(str)).toLocaleDateString(defaultlang, options);

要将时间转换为本地时间,请使用 toLocaleTimeString() 方法。

var time = (new Date(str)).toLocaleTimeString(defaultlang, options);

【讨论】:

【参考方案5】:

在 JS 中,除了如上所述转换每个属性之外,没有简单且跨平台的方法来格式化本地日期时间。

这是我用来获取本地 YYYY-MM-DD 的快速技巧。请注意,这是一个 hack,因为最终日期将不再具有正确的时区(因此您必须忽略时区)。如果我还需要其他任何东西,我会使用 moment.js。

var d = new Date();    
d = new Date(d.getTime() - d.getTimezoneOffset() * 60000)
var yyyymmdd = t.toISOString().slice(0,0); 
// 2017-05-09T08:24:26.581Z (but this is not UTC)

d.getTimezoneOffset() 以分钟为单位返回时区偏移量,d.getTime() 以毫秒为单位,因此 x 60,000。

【讨论】:

@VG 我添加了更多关于 60k 来自何处的信息。希望对您有所帮助。【参考方案6】:

到目前为止,我将答案混合并添加到其中,因为我必须阅读所有答案并额外调查一段时间才能以用户本地时区格式显示来自 db 的日期时间字符串。

日期时间字符串来自 python/django 数据库,格式为:2016-12-05T15:12:24.215Z

在 JavaScript 中可靠地检测浏览器语言似乎不适用于所有浏览器(请参阅JavaScript for detecting browser language preference),因此我从服务器获取浏览器语言。

Python/Django:发送请求浏览器语言作为上下文参数:

language = request.META.get('HTTP_ACCEPT_LANGUAGE')
return render(request, 'cssexy/index.html',  "language": language )

HTML:将其写入隐藏输入中:

<input type="hidden" id="browserlanguage" value= language />

JavaScript:获取隐藏输入的值,例如en-GB,en-US;q=0.8,en;q=0.6/ 然后仅通过替换和正则表达式取列表中的第一种语言

const browserlanguage = document.getElementById("browserlanguage").value;
var defaultlang = browserlanguage.replace(/(\w2\-\w2),.*/, "$1");

JavaScript:转换为日期时间并格式化:

var options =  hour: "2-digit", minute: "2-digit" ;
var dt = (new Date(str)).toLocaleDateString(defaultlang, options);

见:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

结果是(浏览器语言为 en-gb):05/12/2016, 14:58

【讨论】:

【参考方案7】:

似乎从 UTC 日期开始最简单的方法是创建一个新的 Date 对象并使用 setUTC… 方法将其设置为您想要的日期/时间。

然后各种toLocale…String 方法将提供本地化输出。

示例:

// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);

console.log(d);                        // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString());       // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString());   // -> 02/28/2004
console.log(d.toLocaleTimeString());   // -> 23:45:26

一些参考资料:

toLocaleString toLocaleDateString toLocaleTimeString getTimezoneOffset

【讨论】:

在 Firefox 中,toLocateDateString() 返回类似于“2014 年 1 月 12 日星期日”的内容.. 嗯,是的,这是一个相当严重的问题。如果您希望日期在浏览器中看起来相同,则使用这些方法将不起作用。任何已知的替代方案? 上述初始化的单行版本:var d = new Date(Date.UTC(2004,1,29,2,45,26)); 值得考虑的是,Chrome(从 v35 开始)在 toLocaleString() 函数中不考虑用户的语言环境。 很抱歉,这种方法在(我在澳大利亚)下不起作用,当我运行上述代码时,日期以美国格式显示。此外,MDN 表示“使用的语言环境和返回的字符串形式完全取决于实现”。【参考方案8】:

使用 php 代码中的日期,我使用了类似的东西..

function getLocalDate(php_date) 
  var dt = new Date(php_date);
  var minutes = dt.getTimezoneOffset();
  dt = new Date(dt.getTime() + minutes*60000);
  return dt;

我们可以这样称呼它

var localdateObj = getLocalDate('2015-09-25T02:57:46');

【讨论】:

问题是关于 JavaScript,而不是 PHP。 答案仅在javascript中,有问题提到服务器日期为UTC。所以服务器可以是任何语言。所以我只回答了 PHP【参考方案9】:

您可以使用以下命令,以分钟为单位报告与 GMT 的时区偏移:

new Date().getTimezoneOffset();

注意: - 这个函数返回一个负数。

【讨论】:

【参考方案10】:

您可以使用new Date().getTimezoneOffset()/60 作为时区。还有一个toLocaleString() 方法用于使用用户的语言环境显示日期。

这是整个列表:Working with Dates

【讨论】:

toLocaleString 对于以用户可能期望的格式显示日期非常不可靠。即使支持 ISO 402,它仍然非常不可靠,并且格式基于一种语言,而不是区域设置。 @RobG 解决方案是什么而不是toLocaleString @user924——你可以使用库,有很多可供选择。 toLocaleString 的问题在于,不同的实现会给出不同的结果,并且对不同语言和地区的支持程度不同。例如。我的系统默认语言不是 en-US,但某些浏览器的 toLocaleString 的默认格式是美国格式,其他浏览器尊重我的系统语言。时区名称也是如此,只是更糟糕的是它们根本没有标准化。 :-( 次要的 nitpick:您应该否定结果以获取以小时为单位的时区:-new Date().getTimezoneOffset()/60【参考方案11】:

我遇到的最佳解决方案是创建 [time display="llll" datetime="UTC TIME" /] 标签,并使用 javascript (jquery) 解析并显示相对于用户时间的标签。

http://momentjs.com/Moment.js

会很好地显示时间。

【讨论】:

【参考方案12】:

getTimeZoneOffset() 和 toLocaleString 适用于基本的日期工作,但如果您需要实时时区支持,请查看mde's TimeZone.js。

this question的回答中讨论了更多选项

【讨论】:

【参考方案13】:

一旦你构建了你的日期对象,这里是一个用于转换的 sn-p:

该函数采用 UTC 格式的 Date 对象和格式字符串。 您将需要一个Date.strftime 原型。

function UTCToLocalTimeString(d, format) 
    if (timeOffsetInHours == null) 
        timeOffsetInHours = (new Date().getTimezoneOffset()/60) * (-1);
    
    d.setHours(d.getHours() + timeOffsetInHours);

    return d.strftime(format);

【讨论】:

你是从哪里来的? 设置小时是否对 Date 对象的 Day/Date/Year 部分有任何影响?好像没有。 @ChristoKiwi — 传递给 setHours 的值应为整数 getTimezoneOffset()/60 可能返回一个小数(例如,印度偏移量 +05:30 将返回 5.5)。小数被截断。否则,设置小时数会更新其他值(将小时数设置为 48 看看会发生什么)。【参考方案14】:

.getTimezoneOffset() 方法以分钟为单位报告时区偏移,从 GMT/UTC 时区“向西”计数,导致偏移值与通常习惯的值相反。 (例如,纽约时间将被报告为 +240 分钟或 +4 小时)

要获得以小时为单位的正常时区偏移量,您需要使用:

var timeOffsetInHours = -(new Date()).getTimezoneOffset()/60

重要细节: 请注意,夏令时会被考虑到结果中 - 所以这个方法给你的实际上是 time 偏移量 - 而不是实际的地理 time-zone 偏移量。

【讨论】:

【参考方案15】:

这是我在过去的项目中使用的:

var myDate = new Date();
var tzo = (myDate.getTimezoneOffset()/60)*(-1);
//get server date value here, the parseInvariant is from MS Ajax, you would need to do something similar on your own
myDate = new Date.parseInvariant('<%=DataCurrentDate%>', 'yyyyMMdd hh:mm:ss');
myDate.setHours(myDate.getHours() + tzo);
//here you would have to get a handle to your span / div to set.  again, I'm using MS Ajax's $get
var dateSpn = $get('dataDate');
dateSpn.innerHTML = myDate.localeFormat('F');

【讨论】:

这是 ASP.NET 特定的东西。 时区偏移量不一定是一小时的倍数,因此getTimezoneOffset()/60 通常会返回一个十进制值。对于 1900 年之前的日期尤其如此,许多地方在分钟和秒内都有偏移。此外,现在需要 javascript 日期来支持历史偏移量。例如。 1890 年,莫斯科的偏移量为 +2:30:17。见Browsers, time zones, Chrome 67 Error【参考方案16】:

不知道如何设置语言环境,但 javascript 是一种客户端技术。

usersLocalTime = new Date();

将包含客户的时间和日期(由他们的浏览器报告,并通过扩展他们所在的计算机报告)。在响应中包含服务器的时间并做一些简单的数学来猜测时间偏移应该是微不足道的。

【讨论】:

以上是关于以用户的语言环境格式和时间偏移显示日期/时间的主要内容,如果未能解决你的问题,请参考以下文章

Java 语言环境和日期格式

如何解析已使用不同语言环境格式化的日期

如何根据语言环境仅显示日期的日期和月份?

本地化:如何格式化日期和数字

如何强制Excel使用Apache POI以西班牙语语言环境显示值

如何从日期选择器设置语言环境格式?