Разбор даты в javascript различается между сафари и хромом - PullRequest
55 голосов
/ 21 июня 2011

У меня есть следующий код

var c = new Date(Date.parse("2011-06-21T14:27:28.593Z"));
console.log(c);

В Chrome он правильно печатает дату на консоли. В сафари это терпит неудачу. Кто прав и главное что лучше справиться с этим?

Ответы [ 9 ]

94 голосов
/ 21 июня 2011

Вы не можете использовать Date.parse. Я предлагаю вам использовать: new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )

Чтобы разбить строку, вы можете попробовать

var s = '2011-06-21T14:27:28.593Z';
var a = s.split(/[^0-9]/);
//for (i=0;i<a.length;i++) { alert(a[i]); }
var d=new Date (a[0],a[1]-1,a[2],a[3],a[4],a[5] );
alert(s+ " "+d);
15 голосов
/ 23 февраля 2012

Я склонен избегать Date.parse, как и на другие ответы на этот вопрос.Кажется, это не переносимый способ надежного обращения с датами.

Вместо этого я использовал что-то вроде функции ниже.Это использует jQuery для отображения массива строк в массив чисел, но это довольно простая зависимость для удаления / изменения.Я также включил то, что считаю разумными значениями по умолчанию, чтобы вы могли анализировать 2007-01-09 и 2007-01-09T09:42:00, используя одну и ту же функцию.

function dateFromString(str) {
  var a = $.map(str.split(/[^0-9]/), function(s) { return parseInt(s, 10) });
  return new Date(a[0], a[1]-1 || 0, a[2] || 1, a[3] || 0, a[4] || 0, a[5] || 0, a[6] || 0);
}
11 голосов
/ 21 июня 2011

Я проверил это в нескольких браузерах, и да, Safari возвращает invalid date.Кстати, вам не нужно использовать Date.parse здесь, просто new Date([datestring]) тоже будет работать.Safari, очевидно, требует большего форматирования строки даты, которую вы предоставляете.Если вы замените «-» на «/», удалите букву «Т» и все после точки (.593Z), это даст вам правильную дату.Этот код протестирован и работает в Safari

var datestr = '2011-06-21T14:27:28.593Z'.split(/[-T.]/);
var safdat = new Date( datestr.slice(0,3).join('/')+' '+datestr[3] );

или с использованием String.replace(...):

new Date("2016-02-17T00:05:01+0000".replace(/-/g,'/').replace('T',' ').replace(/(\..*|\+.*/,""))
9 голосов
/ 06 марта 2018

Моя похожая проблема была вызвана тем, что Safari не знал, как читать часовой пояс в формате часового пояса RFC 822.Мне удалось это исправить с помощью формата ISO 8601.Если у вас есть контроль над форматом даты, я работал с SimpleDateFormat java "yyyy-MM-dd'T'HH: mm: ss.sssXXX", который производит для меня, т.е."2018-02-06T20: 00: 00,000 + 04: 00".По какой-либо причине Safari не может читать «2018-02-06T20: 00: 00.000 + 0400», обратите внимание на отсутствие двоеточия в формате часового пояса.

// Works
var c = new Date("2018-02-06T20:00:00.000+04:00"));
console.log(c);

// Doesn't work
var c = new Date("2018-02-06T20:00:00.000+0400"));
console.log(c);
5 голосов
/ 14 сентября 2011

В итоге я использовал библиотеку для компенсации этого:

http://zetafleet.com/blog/javascript-dateparse-for-iso-8601

Как только эта библиотека была включена, вы используете этот код для создания новой даты:

var date = new Date(Date.parse(datestring));

В нашем проекте не использовались указатели миллисекунд, но я не верю, что это вызовет у вас проблемы.

4 голосов
/ 10 февраля 2017

Я использую следующую функцию для разбора дат с часовым поясом. Отлично работает как Chrome, так и Safari:

function parseDate(date) {
  const parsed = Date.parse(date);
  if (!isNaN(parsed)) {
    return parsed;
  }

  return Date.parse(date.replace(/-/g, '/').replace(/[a-z]+/gi, ' '));
}

console.log(parseDate('2017-02-09T13:22:18+0300'));  // 1486635738000 time in ms
1 голос
/ 27 января 2016

Я попытался преобразовать дату, обрезав ее и проанализировав так, она отлично работает с сафари и ios.

var dateString = "2016-01-22T08:18:10.000+0000";
 var hours = parseInt(dateString.split("+")[1].substr("0","2"));
 var mins = parseInt(dateString.split("+")[1].substr("2"));
 var date = new Date(dateString.split("+")[0]);
 date.setHours(date.getHours()-hours);
 date.setMinutes(date.getMinutes()-mins);
0 голосов
/ 11 января 2019

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

function newDate(value) {
  var field = value.match(/^([+-]?\d{4}(?!\d\d\b))(?:-?(?:(0[1-9]|1[0-2])(?:-?([12]\d|0[1-9]|3[01]))?)(?:[T\s](?:(?:([01]\d|2[0-3])(?::?([0-5]\d))?|24\:?00)([.,]\d+(?!:))?)?(?::?([0-5]\d)(?:[.,](\d+))?)?([zZ]|([+-](?:[01]\d|2[0-3])):?([0-5]\d)?)?)?)?$/) || [];
  var result = new Date(field[1], field[2] - 1 | 0, field[3] || 1, field[4] | 0, field[5] | 0, field[7] | 0, field[8] | 0)
  if (field[9]) {
    result.setUTCMinutes(result.getUTCMinutes() - result.getTimezoneOffset() - ((field[10] * 60 + +field[11]) || 0));
  }
  return result;
}

console.log(newDate('2011-06-21T14:27:28.593Z'));
console.log(newDate('1970-12-31T06:00Z'));
console.log(newDate('1970-12-31T06:00-1200'));
0 голосов
/ 27 апреля 2018

Вместо использования Z в конце строки даты, вы можете добавить смещение часового пояса локального клиента.Возможно, вам понадобится метод для его генерации:

let timezoneOffset = () => {
    let date = new Date(),
        timezoneOffset = date.getTimezoneOffset(),
        hours = ('00' + Math.floor(Math.abs(timezoneOffset/60))).slice(-2),
        minutes = ('00' + Math.abs(timezoneOffset%60)).slice(-2),
        string = (timezoneOffset >= 0 ? '-' : '+') + hours + ':' + minutes;
    return string;
}

Таким образом, конечный результат будет:

var c = new Date("2011-06-21T14:27:28.593" + timezoneOffset());

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...