我希望服务器总是以HTML格式提供UTC格式的日期,并让客户机站点上的javascript将其转换为用户的本地时区。
如果我能以用户的区域设置日期格式输出,我会得到额外的奖励。
从UTC日期开始,最简单的方法似乎是创建一个新的Date对象,并使用setUTC…方法将其设置为所需的日期/时间。
然后各种toLocale…String方法将提供本地化输出。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| // 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 |
一些参考文献:
- 托卡拉弦
- ToLocaledateString
- Tolocaletimestring
- GetTimeZoneOffset
对于新项目,只需使用moment.js
这个问题很古老,所以moment.js当时不存在,但是对于新项目,它可以简化很多这样的任务。
最好按如下方式分析来自UTC的日期字符串(在服务器上创建一个与ISO-8601兼容的字符串,以便在所有浏览器中获得一致的结果):
1
| var m = moment("2013-02-08T09:30:26Z"); |
现在只需在应用程序中使用m,moment.js默认为本地时区进行显示操作。有很多方法可以格式化日期和时间值或提取其中的一部分。
您甚至可以在用户区域设置中设置矩对象的格式,如下所示:
1
| m.format('LLL') // Returns"February 8 2013 8:30 AM" on en-us |
要将moment.js对象转换为不同的时区(即既不是本地的也不是UTC),您需要moment.js时区扩展。这个页面还有一些例子,使用起来非常简单。
您可以使用new Date().getTimezoneOffset()/60作为时区。还有一个使用用户区域设置显示日期的toLocaleString()方法。
以下是整个列表:使用日期
一旦构建了日期对象,下面是转换的一个片段:
函数接受一个UTC格式的日期对象和格式字符串。您将需要一个Date.strftime原型。
1 2 3 4 5 6 7 8
| function UTCToLocalTimeString(d, format) {
if (timeOffsetInHours == null) {
timeOffsetInHours = (new Date().getTimezoneOffset()/60) * (-1);
}
d.setHours(d.getHours() + timeOffsetInHours);
return d.strftime(format);
} |
以下是我在过去项目中使用的内容:
1 2 3 4 5 6 7 8
| 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'); |
在JS中,除了转换上面提到的每个属性之外,没有简单的跨平台的方法来格式化本地日期时间。
这里有一个快速的黑客,我用来获取本地的YYYY-MM-DD。注意这是一个黑客,因为最终日期将不再有正确的时区(所以你必须忽略时区)。如果我还需要其他东西,我使用moment.js。
1 2 3 4
| 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 60000。
我混合了迄今为止的答案并添加到其中,因为我必须阅读所有答案并额外调查一段时间,才能以用户的本地时区格式显示数据库中的日期-时间字符串。
datetime字符串来自python/django数据库,格式为:2016-12-05t15:12:24.215z
在javascript中可靠地检测浏览器语言在所有浏览器中似乎都不起作用(请参阅javascript以检测浏览器语言首选项),因此我从服务器获取浏览器语言。
python/django:将请求浏览器语言作为上下文参数发送:
1 2
| language = request.META.get('HTTP_ACCEPT_LANGUAGE')
return render(request, 'cssexy/index.html', {"language": language }) |
HTML:将其写入隐藏输入:
1
| <input type="hidden" id="browserlanguage" value={{ language }}/> |
javascript:获取隐藏输入的值,例如en-gb、en-us;q=0.8、en;q=0.6/,然后仅通过replace和正则表达式获取列表中的第一种语言
1 2
| const browserlanguage = document.getElementById("browserlanguage").value;
var defaultlang = browserlanguage.replace(/(\w{2}\-\w{2}),.*/,"$1"); |
javascript:转换为日期时间并格式化:
1 2
| 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
使用PHP代码中的日期,我使用了类似的方法。
1 2 3 4 5 6
| function getLocalDate(php_date) {
var dt = new Date(php_date);
var minutes = dt.getTimezoneOffset();
dt = new Date(dt.getTime() + minutes*60000);
return dt;
} |
我们可以这样称呼它
1
| var localdateObj = getLocalDate('2015-09-25T02:57:46'); |
.getTimezoneOffset()方法以分钟为单位报告时区偏移量,从gmt/utc时区算起"向西",得出的偏移量值与人们通常习惯的值相反。(例如,纽约时间报告为+240分钟或+4小时)
要获得以小时为单位的正常时区偏移量,需要使用:
1
| var timeOffsetInHours = -(new Date()).getTimezoneOffset()/60 |
重要细节:请注意,夏令时是计算结果的因素,所以这个方法给出的实际上是时间偏移量,而不是实际的地理时区偏移量。
我遇到的最佳解决方案是创建[time display="llll"datetime="utc time"/]标记,并使用javascript(jquery)相对于用户的时间来解析和显示它。
网址:http://moment js.com/moment.js
会很好地显示时间。
您可以使用以下报告时区与格林尼治标准时间(以分钟为单位)的偏移量:
1
| new Date().getTimezoneOffset(); |
注:-此函数返回一个负数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| // 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); |
getTimeZoneOffset()和toLocaleString适合于基本的日期工作,但是如果需要实时区域支持,请查看MDE的timeZone.js。
在这个问题的答案中,还有几个选项要讨论
要将日期转换为本地日期,请使用toLocaledateString()方法。
1
| var date = (new Date(str)).toLocaleDateString(defaultlang, options); |
要将时间转换为本地时间,请使用toLocaletimeString()方法。
1
| var time = (new Date(str)).toLocaleTimeString(defaultlang, options); |
不知道如何进行区域设置,但javascript是客户端技术。
1
| usersLocalTime = new Date(); |
将包含客户的时间和日期(由他们的浏览器报告,并通过扩展他们所在的计算机)。将服务器的时间包括在响应中,并进行一些简单的数学运算来猜测时间偏移量,这应该是很简单的事情。