Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用CET作为默认时区在javascript中解析日期_Javascript_Date_Parsing_Timezone_Timezone Offset - Fatal编程技术网

使用CET作为默认时区在javascript中解析日期

使用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格式的日期字符串,如果没有指定时区,则

我有一些传统的Web服务,有时不本地化日期。有时会,所以我必须支持这两种情况

他们应始终使用意大利的地区设置(UTC+1表示标准时间,UTC+2表示夏令时),但有时他们返回的日期忽略了日期ISO字符串末尾的时区

例如,意大利语新年应该是2018-01-01T00:00:00+0100,而它们只返回
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"