Остановить функцию javascript Date от изменения смещения временной зоны

Итак, у меня есть iso date time, которые необходимо преобразовать из объекта с привязкой к текущей. Как сохранить дату перехода на локальный часовой пояс браузера.

new Date('2013-07-18T17:00:00-05:00')
Thu Jul 18 2013 18:00:00 GMT-0400 (EDT)

Я хочу получить

Thu Jul 18 2013 17:00:00 GMT-0500 (XX)

Ответы

Ответ 1

Вы не можете изменить это поведение Javascript, потому что это единственный простой способ работы Javascript. Случается, что Javascript просматривает временной сдвиг, вычисляет совпадающую временную метку и затем запрашивает ОС для представления этой метки времени в локальном часовом поясе. Здесь важно понять, что -05:00 не является указанием часового пояса, а просто сдвигом с UTC.

Часовые пояса - это сложные звери, которые являются просто произвольными политическими решениями. ОС предоставляет услугу для отображения времени в локальном часовом поясе, но не в других часовых поясах. Для этого вам нужно принимать во внимание такие вещи, как DST, которые в значительной степени ада.

Как всегда с управлением временем, единственный достойный способ решить эту проблему - использовать специальную библиотеку. В Javascript вы найдете Moment.js и Moment.Timezone.js очень полезно.

Пример http://codepen.io/Xowap/pen/XKpKZb?editors=0010

document.write(moment('2013-07-18T17:00:00-05:00').tz('America/New_York').format('LLL'));

В качестве бонуса вы получаете тонну функций форматирования/разбора из Moment.js.

Также обратите внимание, что до тех пор, пока вы используете ISO 8601, ваша дата может быть точно определена и, таким образом, будет отображаться в любой временной зоне по вашему вкусу. Другими словами, JS "преобразование" вашей даты не имеет значения.

Ответ 2

Для этого вы можете использовать библиотеку, такую ​​как Moment.js.

Смотрите синтаксический анализ Строка + Формат.

http://momentjs.com/docs/#/parsing/string-format/

Следующее должно проанализировать предоставленную вами дату, но вам может потребоваться изменить ее для ваших нужд.

var dateString = "2013-07-18T17:00:00-05:00";

var dateObject = moment(dateString, "YYYY-MM-DDTHH:mm:ssZ").toDate();

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

http://momentjs.com/docs/#/parsing/string/

Ответ 3

Хотя MomentJS - отличная библиотека, она не может обеспечить решение для каждого варианта использования. Например, мой сервер предоставляет даты в формате UTC, и когда часть времени даты не сохраняется в БД (потому что это не имеет значения), клиент получает строку со временем по умолчанию всех нулей - полночь - и оканчивается на смещение +0000. Затем браузер автоматически подстраивается под мой локальный часовой пояс и тянет время назад на несколько часов, что приводит к предыдущему дню.

Это верно и для MomentJ.

Одно из решений состоит в том, чтобы отрезать временную часть строки, а затем использовать MomentJS, как описано в других ответах.

Но что произойдет, если MomentJS не является жизнеспособным вариантом, то есть у меня уже есть много мест, которые используют JS Date и не хотят обновлять так много строк кода? Вопрос в том, как остановить браузер от конвертации дат в зависимости от локального часового пояса. И ответ таков: когда дата в формате ISO, вы не можете.

Однако не существует правила, согласно которому строка, передаваемая в конструктор JavaScript, должна быть в формате ISO. Если вы просто замените - который разделяет год, месяц и день на /, ваш браузер не выполнит конвертацию.

В моем случае я просто изменил формат серверной части Dates, и проблема была решена без необходимости обновлять все даты JS на стороне клиента с помощью MomentJS.

Обратите внимание, что документы MDN для класса Date JavaScript предупреждают о непредсказуемом поведении браузера при разборе строки для создания экземпляра Date.

Ответ 4

Интересно, поможет ли это:

function goAheadMakeMyDate(s){
  var d = new Date(s);
  // override Date.toString()
  d.toString = function(){ return ''+s; };
  return d;
}

var example = goAheadMakeMyDate("Fri 19 July 2013 12:00:00 GMT");

example.toString() // returns string actually used to construct the date
'Fri 19 July 2013 12:00:00 GMT'

example.toLocaleString()
'Fri Jul 19 2013 08:00:00 GMT-0400 (EDT)'

1*example // gives seconds since epoch
1374235200000

С вашим вводом:

example = goAheadMakeMyDate('2013-07-18T17:00:00-05:00')
{ Thu, 18 Jul 2013 22:00:00 GMT toString: [Function] }
> example.toString()
'2013-07-18T17:00:00-05:00'
> example.toLocaleString() // I live in GMT-4
'Thu Jul 18 2013 18:00:00 GMT-0400 (EDT)'
> 1*example  // convert to integer date
1374184800000

Однако, если вы начнете изменять эту дату, toString не изменится и вас укусит.

Ответ 5

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

Во многих случаях самый простой способ отформатировать и отобразить строку даты-времени в полученном часовом поясе - вообще не преобразовывать строку в объект Date. Вместо этого просто проанализируйте строку даты и времени и объедините части в желаемый формат. Например, если вы можете прожить без дня недели в выходных данных, запрошенных в вопросе, вы можете сделать что-то вроде следующего для обработки запрошенного формата ввода и вывода (в том числе день недели добавляет достаточно сложности, чтобы это могло быть стоит использовать библиотеку на тот момент). Конечно, этот подход требует модификации на основе формата строк даты и времени, которые вы получаете на стороне клиента.

const months = {1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'};

const format = (datetime) => {
  let [date, time] = datetime.split('T');
  let [y, m, d] = date.match(/\d+/g);
  let [t, tz] = time.split(/(?=[+-])/);
  return '${months[parseInt(m)]} ${d} ${y} ${t} GMT${tz}';
}

let dt = format('2013-07-18T17:00:00-05:00');
console.log(dt);
// Jul 18 2013 17:00:00 GMT-05:00

Ответ 6

Если вы открыты для использования библиотеки, библиотека JavaScript MomentJS является популярной для обработки времени и дат.