使用CET作为默认时区在javascript中解析日期
我有一些传统的Web服务,有时不本地化日期。有时会,所以我必须支持这两种情况 他们应始终使用意大利的地区设置(UTC+1表示标准时间,UTC+2表示夏令时),但有时他们返回的日期忽略了日期ISO字符串末尾的时区 例如,意大利语新年应该是2018-01-01T00:00:00+0100,而它们只返回使用CET作为默认时区在javascript中解析日期,javascript,date,parsing,timezone,timezone-offset,Javascript,Date,Parsing,Timezone,Timezone Offset,我有一些传统的Web服务,有时不本地化日期。有时会,所以我必须支持这两种情况 他们应始终使用意大利的地区设置(UTC+1表示标准时间,UTC+2表示夏令时),但有时他们返回的日期忽略了日期ISO字符串末尾的时区 例如,意大利语新年应该是2018-01-01T00:00:00+0100,而它们只返回2018-01-01T00:00:00 这会导致Javascript中出现错误行为,尤其是在处理截止日期和位于其他时区的客户端时 我希望能够编写一段代码来解析ISO格式的日期字符串,如果没有指定时区,则
2018-01-01T00:00:00
这会导致Javascript中出现错误行为,尤其是在处理截止日期和位于其他时区的客户端时
我希望能够编写一段代码来解析ISO格式的日期字符串,如果没有指定时区,则假设使用意大利本地化
我的代码几乎没有问题(它不解析毫秒,但我可以接受),不幸的是,当浏览器在没有夏令时的时区执行时,它会失败。我该怎么办?我错过什么了吗
提前谢谢
/**
* Get the local timezone using standard time (no daylight saving time).
*/
Date.prototype.stdTimezoneOffset = function() {
var jan = new Date(this.getFullYear(), 0, 1);
var jul = new Date(this.getFullYear(), 6, 1);
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
}
/**
* Check whether current time is daylight saving time.
*/
Date.prototype.isDst = function() {
return this.getTimezoneOffset() < this.stdTimezoneOffset();
}
/**
* Check whether daylight saving time is observed in current timezone.
*/
Date.prototype.isDstObserved = function() {
var jan = new Date(this.getFullYear(), 0, 1);
var jul = new Date(this.getFullYear(), 6, 1);
return jan.getTimezoneOffset() != jul.getTimezoneOffset();
}
/**
* Cross-browser parse of a date using CET as default timezone.
*/
Date.parseFromCET = function(str) {
if (str == null) return null;
// split the input string into an array of integers
var a = str.split(/[^0-9]/)
.map(function(s) {
return parseInt(s, 10)
});
var b = new Date(
a[0], // yyyy
a[1] - 1 || 0, // MM
a[2] || 1, // dd
a[3] || 0, // hh
a[4] || 0, // mm
a[5] || 0 // ss
);
// if no timezone is present, force to CET
if (str.lastIndexOf('-') <= 7 && str.indexOf('+') == -1 && str.indexOf('Z') == -1) {
var CET_timezone_offset = b.isDst() ? '+0200' : '+0100'
var isoString = a[0] + '-' + a[1] + '-' + a[2] + 'T' +
a[3] + ':' + a[4] + ':' + a[5] + CET_timezone_offset;
return Date.parseFromCET(isoString);
}
// remove local timezone offset to go from UTC time to local time
b.setMinutes(b.getMinutes() - b.getTimezoneOffset());
// add/remove forced timezone offset to calculate exact local time
if (str.indexOf('+') > -1) {
let hours = Math.floor(a[a.length - 1] / 100);
let minutes = a[a.length - 1] % 100;
b.setMinutes(b.getMinutes() - minutes);
b.setHours(b.getHours() - hours);
}
if (str.lastIndexOf('-') > 7) {
let hours = Math.floor(a[a.length - 1] / 100);
let minutes = a[a.length - 1] % 100;
b.setMinutes(b.getMinutes() + minutes);
b.setHours(b.getHours() + hours);
}
return b;
}
/**
*使用标准时间(无夏令时)获取本地时区。
*/
Date.prototype.stdtTimeZoneOffset=函数(){
var jan=新日期(this.getFullYear(),0,1);
var jul=新日期(this.getFullYear(),6,1);
返回Math.max(jan.getTimezoneOffset(),jul.getTimezoneOffset());
}
/**
*检查当前时间是否为夏令时。
*/
Date.prototype.isDst=函数(){
返回此.getTimezoneOffset()7){
让小时数=数学楼层(a[a.长度-1]/100);
分钟=a[a.长度-1]%100;
b、 setMinutes(b.getMinutes()+分钟);
b、 设定小时数(b.getHours()+小时数);
}
返回b;
}
时间戳与ECMA-262中的格式不一致,因为偏移量中缺少冒号。因此,解析依赖于实现,您可能会得到一个无效的日期(例如在Safari中)
罗马的标准偏移量为+01:00。夏时制从3月最后一个星期日的02:00开始(更改为+02:00),到10月最后一个星期日的02:00结束(返回到+01:00)
请注意,已经发生了历史性的变化。意大利在1916年开始使用夏时制,但也有一段时间它没有被观察到。自1965年以来,它一直被观察,所以只要你的日期在那之后,你就不必担心过去的变化,只需要担心未来的变化
下面是一种方法,它需要更多的测试,应该对输入字符串和结果日期对象进行验证。您可能还应该处理“Z”时区
如果你打算经常这样做,一个管理时区的库将非常有帮助,因为它还应该处理历史变化、过去和未来
/**获取当月最后一个星期日的日期
*@param{number | string}年份-月份的年份
*@param{number | string}month-日历月数,1=1月,2=2月,等等。
*@returns{Date}给定年份和月份的最后一个星期日的日期
*/
函数getLastSunday(年、月){
//每月最后一天的日期
var d=新日期(日期UTC(年、月、0));
//调整到上周日
d、 setUTCDate(d.getUTCDate()-d.getUTCDay());
返回d;
}
/**返回设置为意大利DST UTC开始的日期
*3月最后一个星期日的+0300 UTC开始
*
*@param{number | string}年开始DST
*@返回{Date}设置为开始日期和+0300Z
*/
函数getDSTStart(年){
var d=getLastSunday(第3年);
d、 刚毛(3);
返回d;
}
/**返回设置为意大利DST UTC结束的日期
*在10月最后一个星期日的+0400 UTC结束
*
*@param{number | string}年开始DST
*@返回{Date}设置为开始日期和+0400Z
*/
函数getDSTEnd(年){
var d=getLastSunday(第10年);
d、 刚毛(4);
返回d;
}
/**给定年、月、日和小时,返回
*正确或错误,取决于DST是否正确
*在意大利被观察到。
*使用UTC以避免本地影响,假设为标准时间
*
*@param{number | string}年份-主题年份
*@param{number | string}月-主题日历月
*@param{number | string}日-主题日
*@param{number | string}小时-主题小时
*@返回所提供日期和时间的{number}偏移量
*/
函数(年、月、日、小时){
var d=新日期(Date.UTC(年、月、日、小时+1));
返回d>=getDSTStart(年)&dlet dt = DateTime.fromISO('2018-01-01T00:00:00+0100', { setZone: true, zone: 'Europe/Rome'});
console.log(dt.toISO()); //=> "2018-01-01T00:00:00.000+01:00"
let dt = DateTime.fromISO('2018-01-01T00:00:00', { setZone: true, zone: 'Europe/Rome'});
console.log(dt.toISO()); //=> "2018-01-01T00:00:00.000+01:00"
let dt = DateTime.fromISO('2018-07-01T00:00:00', { setZone: true, zone: 'Europe/Rome'});
console.log(dt.toISO()); //=> "2018-07-01T00:00:00.000+02:00"