2013-03-20 2 views
21

У меня есть дата ISO строку, как показано нижеКак определить местный часовой пояс при разборе даты ISO 8601?

var startTimeISOString = "2013-03-10T02:00:00Z"; 

, когда я преобразовать его в дату объекта в JavaScript, используя ниже код, он возвращает

var startTimeDate = new Date(startTimeISOString); 

о/р

Date {Sun Mar 10 2013 07:30:00 GMT+0530 (India Standard Time)} 

Он уверен, преобразует ISOString на сегодняшний день, но преобразует его в lo время, так как новая Date() зависит от клиента. Как просто преобразовать строку даты даты iso в дату и время, но не в локальное время.

Благодаря

+1

Ваше время ISO заканчивается на «Z», что означает UTC (GMT). Если время на самом деле является локальным для начала, вы должны заменить «Z» на «+0530». Но если вы хотите совершить кругосветное путешествие, вы должны сохранить строчную версию в UTC. –

+0

вы можете пояснить, что вы пытаетесь создать строковое представление, которое сохраняет исходный часовой пояс, в данном случае Zulu (Z), вместо того, чтобы повторно интерпретировать время в часовом поясе компьютера, на котором запущен код. Похоже, вы есть, но это не на 100% ясно. –

ответ

44

According to MDN:

Различия в предполагаемом часовом поясе

Учитывая строку даты «7 марта 2014 года», parse() принимает местное время зоны, но с учетом формата ISO, такого как «2014-03-07», он примет часовой пояс UTC.Поэтому объекты Date, созданные с использованием этих строк , будут представлять разные моменты времени, если система не установлена ​​с местным часовым поясом UTC. Это означает, что две строки даты, которые отображаются эквивалентом , могут приводить к двум различным значениям в зависимости от формата строки, которая преобразуется (это изменение изменяется в ECMAScript ed 6, так что оба будут рассматриваться как локальные).

Я сделал так, и я теперь получаю точное время, которое находится внутри строки даты ISO вместо местного времени

var startTimeISOString = "2013-03-10T02:00:00Z"; 

var startTime = new Date(startTimeISOString); 
startTime = new Date(startTime.getTime() + (startTime.getTimezoneOffset() * 60000)); 

Это даст то же самое время о дате в дате изо строки, выход здесь

о/р

Date {Sun Mar 10 2013 02:00:00 GMT+0530 (India Standard Time)} 
+0

Я не вижу, что детали функции синтаксиса имеют какое-либо отношение к этому. В приведенном ниже параграфе MDN указывается, что синтаксический анализ просматривает формат строки и определяет, является ли формат RFC2822 или ISO8601. –

+0

Ответ здесь дает правильный час дня, но это опасно, потому что вы по-прежнему находитесь в другом часовом поясе до первоначального времени. Правильный ответ создаст объект даты с тем же часовым поясом, что и оригинал. –

+0

Обратите внимание, что getTimezoneOffset - это разница между UTC и local, что дает противоположное тому, что можно было бы ожидать. Из MDN: «Обратите внимание, что это означает, что смещение является положительным, если местный часовой пояс находится за UTC и отрицательный, если он впереди. Например, если ваш часовой пояс UTC + 10 (австралийское восточное стандартное время), будет возвращен -600 . » –

5

Это происходит потому, что дата печатается с использованием toString метода, который по умолчанию возвращает дату и время в местном часовом поясе. Метод toUTCString предоставит вам нужную вам строку.

Date фактически сохраняет дату как единое время в миллисекундах и предоставляет методы для ее управления.

+0

Могу ли я использовать его как объект даты, а не строку? прямо сейчас он возвращает строку, но мне нужно, чтобы это был объект даты, так как я делаю сравнения дат с другой датой – CrazyNooB

+0

Поскольку объект даты хранит время unix, вы можете использовать методы UTC везде, где это необходимо. См. Методы UTC в Date: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date – Diode

+0

getUTCDate, getUTCMonth и т. Д. – Diode

9

Подытоживая разговор с поста tracevipin в:

Все объекты Дата основаны на time value, который миллисекунды так 1970-01-01T00: 00: 00Z так они UTC в их основе. Это отличается от UNIX, который использует значение, представляющее секунды с той же эпохи.

Метод Date.prototype.toString возвращает строку, зависящую от реализации, которая представляет время, основанное на настройках системы и смещении часового пояса клиента (ака местного времени).

Если требуется временная строка UTC ISO8601, может использоваться метод Date.prototype.toISOString. Очень легко написать «прокладку» для этих методов, если это необходимо.

И, наконец, не доверяйте Date.parse, чтобы разобрать строку. Поддержка UTC-строки формата ISO8601 указана в ES5, однако она не применяется последовательно во всех используемых браузерах. Гораздо лучше разобрать строку вручную (это не сложно, есть примеры на SO о том, как это сделать), если требуется широкая поддержка браузера (например, типичное веб-приложение).

Простой ISO8601 UTC метка времени парсер:

function dateObjectFromUTC(s) { 
    s = s.split(/\D/); 
    return new Date(Date.UTC(+s[0], --s[1], +s[2], +s[3], +s[4], +s[5], 0)); 
} 

и вот прокладка для toISOString:

if (typeof Date.prototype.toISOString != 'function') { 

    Date.prototype.toISOString = (function() { 

    function z(n){return (n<10? '0' : '') + n;} 
    function p(n){ 
     n = n < 10? z(n) : n; 
     return n < 100? z(n) : n; 
    } 

    return function() { 
     return this.getUTCFullYear() + '-' + 
      z(this.getUTCMonth() + 1) + '-' + 
      z(this.getUTCDate()) + 'T' + 
      z(this.getUTCHours()) + ':' + 
      z(this.getUTCMinutes()) + ':' + 
      z(this.getUTCSeconds()) + '.' + 
      p(this.getUTCMilliseconds()) + 'Z'; 
    } 
    }()); 
} 
+0

Вы должны изменить свое регулярное выражение на '/ [\ - \. \ +: TZ]/g' –

+0

@ OnurYıldırım - вы правы, он не правильно разделяет строку, самым простым RegExp для использования является '/ \ D /'. Он не предназначен как общий синтаксический анализатор ISO 8601, это очень большая работа. – RobG

+0

Строки ISO и UTC - две разные вещи. Это не приведет к созданию строки ISO 8601. ISO 8601 кодирует часовой пояс, это не будет (из-за использования getUTC ...) –

1

в ваниль javascript не существует способа создать дату, предполагающую местное время отформатированной строки ISO, которую вы ему даете. Вот что происходит, когда вы передаете форматированную строку ISO 8601 в javascript. Я собираюсь использовать не время UTC, как это иллюстрирует проблему лучше, чем при использовании ISO отформатированной строки:

  1. вара STARTTIME = новая Даты («2013-03-10T02: 00: 00 + 06: 00»). Обратите внимание, что это также может быть «2013-03-10T02: 00: 00Z» или любая другая строка в формате ISO.
  2. прочитайте время, примените смещение и вычислите миллисекунды с 1970-01-01T00: 00: 00Z
  3. Теперь у вас есть только миллисекунды - вы потеряли всю информацию о часовом поясе. В этом случае 1362859200000

Все функции, кроме тех, которые дают вам UTC-представление этого числа, будут использовать часовой пояс компьютера, на котором выполняется код, чтобы интерпретировать этот номер как время.

Чтобы сделать то, что хочет исходный плакат, вам нужно.

  1. разбора строки ISO, интерпретировать смещение («Z» или «+06: 00»), как смещение часового пояса
  2. магазин временная зона смещения
  3. вычислять и хранить мс с начала эпохи, используя смещение смещения временной шкалы
  4. Удерживайте это смещение
  5. При попытке произвести расчет или распечатать дату примените смещение часового пояса.

Это не тривиально и требует полной интерпретации спецификации 8601. Путь слишком много кода, чтобы положить здесь.

Это именно то, что нужно сделать moment.js. Я настоятельно рекомендую использовать его. Использование момента.js:

moment("2013-03-10T02:00:00Z").format() 
"2013-03-10T02:00:00Z" 

это приведет к печати времени ISO исходной строки, сохраняя смещение.

Смежные вопросы