Создание нового объекта даты, который включает идентификатор часового пояса

Я запрашиваю время начала события из API Facebook. Чаще всего они возвращают строку, подобную следующей:

2014-04-02T20:00:00-0600

Но иногда он возвращается как:

2014-04-19

Когда я пытаюсь создать новый объект даты, он не работает с идентификатором часового пояса.

Однако оба они работают:

var d = new Date('2014-04-02T20:00:00')

or

var d = new Date('2014-04-19')

Но мне нужно, чтобы это работало:

var d = new Date('2014-04-02T20:00:00-0600')
// returns Invalid Date

Я пытаюсь избежать синтаксического анализа каждой строки start_time, чтобы узнать, нужно ли мне удалить идентификатор часового пояса, поскольку я работаю с сотнями событий.

Есть ли более простой способ сделать то, что я пытаюсь сделать, или мне действительно нужно удалить идентификатор часового пояса для каждой даты, в которой он есть?


person KevBot    schedule 03.04.2014    source источник
comment
Помогает ли это — engineering.nulogy.com/posts/?   -  person pj013    schedule 03.04.2014
comment
Вам нужно будет вручную проанализировать строку. Это не сложно, вам нужно написать код только один раз. Но вам нужно точно сказать, что вы хотите сделать. Вы хотите преобразовать, скажем, 2014-04-02T20:00:00-0600 в местное время пользователя или представить его в определенном часовом поясе (например, UTC)?   -  person RobG    schedule 03.04.2014
comment
Вы пытались использовать класс timestamptz?   -  person Roby Sottini    schedule 03.04.2014
comment
@ jp310 Да, это полезная информация. Я пытался избежать использования библиотек moment.js. Но я приму это во внимание.   -  person KevBot    schedule 03.04.2014
comment
@RobG Да, я знаю, что это не сложно. Это хорошее понимание того, хочу ли я что-то делать со смещением в частности.   -  person KevBot    schedule 03.04.2014


Ответы (1)


Вы можете проанализировать строку ISO 8601 со смещением, используя следующее. Если строка не имеет смещения, предполагается, что она равна Z (т. е. UTC согласно ECMA-262):

/* Parse an ISO string with an offset
**   e.g. '2014-04-02T20:00:00-0600'
**        '2014-04-02T20:00:00Z'
**
** Allows decimal seconds if supplied
**   e.g. '2014-04-02T20:00:00.123-0600'
**
** If no offset is supplied (or it's Z), treat as UTC (per ECMA-262)
** If date only, e.g. '2014-04-02', treat as UTC date (per ECMA-262)
*/
function parseISOString(s) {
  var t = s.split(/\D+/g);
  var hasOffset = /\d{2}[-+]\d{4}$/.test(s);

  // Whether decimal seconds are present changes the offset field and ms value
  var hasDecimalSeconds = /T\d{2}:\d{2}:\d{2}\.\d+/i.test(s);
  var offset = hasDecimalSeconds? t[7] : t[6];
  var ms = hasDecimalSeconds? t[6] : 0;
  var offMin, offSign, min;

  // If there's an offset, apply it to minutes to get a UTC time value
  if (hasOffset) {
    offMin = 60 * offset / 100 + offset % 100;
    offSign = /-\d{4}$/.test(s)? -1 : 1;
  }
  min = hasOffset? +t[4] - offMin * offSign : (t[4] || 0);

  // Return a date object based on UTC values
  return new Date(Date.UTC(t[0], --t[1], t[2], t[3]||0, min, t[5]||0, ms));
}

// Tests
console.log(parseISOString('2014-04-02T20:00:00-0600').toISOString());    // 2014-04-03T02:00:00.000Z
console.log(parseISOString('2014-04-02T20:00:00Z').toISOString());        // 2014-04-02T20:00:00.000Z
console.log(parseISOString('2014-04-02T20:00:00').toISOString());         // 2014-04-02T20:00:00.000Z
console.log(parseISOString('2014-04-02T20:00:00.123-0600').toISOString());// 2014-04-03T02:00:00.123Z
console.log(parseISOString('2014-04-02T20:00:00.123').toISOString());     // 2014-04-02T20:00:00.123Z
console.log(parseISOString('2014-04-02').toISOString());                  // 2014-04-02T00:00:00.000Z

Обратите внимание, что если это создаст объект даты со смещением для часового пояса среды хоста на основе настроек системы. Значением времени Date будет эквивалентное время UTC для предоставленной метки времени (в данном случае «2014-04-03T02:00:00Z»). Вы можете подтвердить это с помощью метода toISOString (требуется IE9 или выше или другой современный браузер).

Редактировать

Обратите внимание, что вы не можете установить смещение часового пояса объекта Date. У них есть значение времени, представляющее момент времени в формате UTC, и смещение часового пояса, основанное на настройках системы. Вы можете прочитать «локальные» значения даты и времени, используя стандартные методы Date, такие как getFullYear и getHours, или значения UTC, если используются методы UTC (например, getUTCFullYear, получитьUTCHours).

Редактировать 2

Разрешен только формат даты (рассматривается как UTC).

person RobG    schedule 03.04.2014
comment
Мне нравится, куда это идет. Однако, как указано в вопросе, иногда start_time для события форматируется как: 2014-04-19, что в этом случае не удастся. Я полагаю, хотя я мог бы использовать это, когда я сталкиваюсь с start_time с идентификатором. - person KevBot; 03.04.2014
comment
Я добавил поддержку формата только даты, он обрабатывается как UTC. Это то, что вам нужно? Довольно легко относиться к этому как к местной дате. - person RobG; 03.04.2014
comment
Отлично, спасибо за ваше время. Гораздо лучше сделать это, чем включать библиотеку. - person KevBot; 03.04.2014