Подтвердить что ты не робот

Разбор даты в javascript отличается между сафари и хром

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

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

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

4b9b3361

Ответ 1

Вы не можете использовать 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);

Ответ 2

Я стараюсь избегать 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);
}

Ответ 3

Я проверил его в нескольких браузерах, и да, сафари вернет invalid date. Кстати, вам не нужно использовать Date.parse здесь, просто new Date([datestring]) тоже будет работать. Очевидно, что Safari требует больше форматирования предоставляемой вами даты. Если вы замените '-' на '/', удалите T и все после точки (.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(/(\..*|\+.*/,""))

Ответ 4

Моя аналогичная проблема была вызвана тем, что Safari не знает, как читать часовой пояс в формате часового пояса RFC 822. Я смог исправить это, используя формат ISO 8601. Если у вас есть контроль формата даты, я получил эту работу с java SimpleDateFormat "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

Я закончил использование библиотеки, чтобы компенсировать это:

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

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

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

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

Ответ 6

Я использую следующую функцию для парсинга дат с часовым поясом. Хорошо работает как 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

Ответ 7

Я попытался преобразовать дату, усекав ее и разобрав ее так, ее работоспособность с сафари и 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);

Ответ 8

Вместо использования "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());

Ответ 9

Вот более надежный парсер 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'));