Описание
Итак, я и мой коллега обнаружили ошибку в нашем коде, которая, как оказалось, была вызвана тем, что мы использовали неопределенную переменную (в основном moment(undefined)
а затем пытались сравнить ее с новым экземпляром момента ( moment()
) методом isSameOrAfter
.
В основном мы использовали следующее:
let isSame = moment(undefined).isSameOrAfter(moment());
Выполнение этого кода один или два раза вернет true
, но не всегда. Время от времени он возвращает false
, я думаю, это потому, что создание двух экземпляров момента друг за другом без определенного времени может создать их с разницей в несколько микросекунд.
Вот тест, который я провел как в Node v7.1.0 в Windows 10, так и в Chrome / 56.0.2924.87 с Moment.js 2.17.1.
const moment = require('moment');
function isSameOrAfter() {
console.log('isSameOrAfter')
for (let i = 0; i < 1000; i++) {
let output = moment().isSameOrAfter(moment());
if (!output) {
console.log(output, i);
}
}
}
function isSame() {
console.log('isSame')
for (let i = 0; i < 1000; i++) {
let output = moment().isSame(moment());
if (!output) {
console.log(output, i);
}
}
}
function sameExactVariable() {
console.log('Another test comparing the same exact variable')
for (let i = 0; i < 1000; i++) {
const now = moment();
let output = now.isSame(now);
if (!output) {
console.log(output, i);
}
}
}
isSameOrAfter();
isSame();
sameExactVariable();
Первые две функции будут регистрировать false
несколько раз из 1000, а третья функция - нет. Он регистрирует только исключение.
Среда:
Вт, 21 февраля 2017 г., 14:36:06 GMT + 0100 (стандартное время западной Европы)
2017-02-21 14:36:06
-60
Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, как Gecko) Chrome / 56.0.2924.87 Safari / 537.36
2.17.1
Наверное, у меня такая же проблема. Он работает должным образом на устройствах Chrome и Android, но не на iOS.
let arrDates: Array<String> = [];
_.each(Dates, (date) => {
if (moment(date).isSameOrAfter(moment().format('MM-DD-YYYY'))) {
arrDates.push(date);
}
});
в iOS я получаю нулевой массив, пока он работает на Chrome и Android.
Среда:
Кордова CLI: 6.4.0
Версия Ionic Framework: 2.0.0
Версия Ionic CLI: 2.1.18
Версия Ionic App Lib: 2.1.9
Версия Ionic App Scripts: 1.0.0
версия ios-deploy: 1.9.0
версия ios-sim: 5.0.13
ОС: macOS Sierra
Версия узла: v6.9.2
Версия Xcode: Xcode 8.2.1 Версия сборки 8C1002
@ErikMartensson
Я предполагаю, что это потому, что создание двух экземпляров момента друг за другом без определенного времени может создать их с разницей в несколько микросекунд.
Да, moment()
или moment(undefined)
- которые идентичны - означает " сейчас" . Даты JS имеют разрешение в миллисекундах, поэтому, если сейчас другая миллисекунда, что иногда случается, один раз за другим. AFAIK, JS не определяет, какой порядок moment().isSameOrAfter(moment())
оценивает эти два вызова moment()
. Но поскольку он, очевидно, в любом случае должен выполнить второй вызов перед выполнением isSameOrAfter()
, меня не удивит, если на практике второй всегда будет первым. Это будет означать, что если есть разница во времени, то часть теста «orAfter» также не удастся. Вы можете подтвердить это с помощью отладчика.
Я не знаю, что тебе сказать. Именно так должны работать даты с конечным разрешением; «сейчас» означает другое время в зависимости от того, когда вы это говорите.
@imrvshah Сначала обратите внимание, что
...isSameOrAfter(moment().format('MM-DD-YYYY'))
создает новый момент с текущим временем, форматирует его как строку и передает эту строку в isSameOrAfter()
, который снова анализирует ее. Вы должны были просто сказать:
...isSameOrAfter(moment())
И сохранил момент -> строка -> момент работы. Это намного лучший код, но я уверен, что он исправляет ошибку. Вы заметили предупреждения об устаревании, в которых говорится: «Эй, вы не должны передавать строки в такой момент»? Moment знает, как разбирать строки ISO 8601, например moment("1982-05-25")
. Он также знает, как анализировать строки, в которых указан формат, например moment("05-25-1982", "MM-DD-YYYY")
. Но он понятия не имеет, что строка типа «05-25-1982» должна быть «ММ-ДД-ГГГГ» без вашего ведома. Таким образом, он позволяет браузеру угадывать, просто передав эту строку конструктору Date
. Другими словами, ваш код разворачивается следующим образом:
m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))
Есть причина, по которой мы отказались от этого: он дает противоречивые результаты в зависимости от того, в каком браузере он запущен. Итак, вы столкнулись с тем, что iOS изначально не поддерживает этот формат. В моей консоли разработчика Safari:
> new Date("05-25-1982")
Invalid Date
Это дало вам плохие сравнения, оставившие вас с пустым массивом.
@icambron
Я согласен с вами и выяснил, что в консоли это предупреждение об устаревании из-за формата даты.
Спасибо за комментарий о том, что не нужно оборачивать его несколько раз, а просто использовать. ...isSameOrAfter(moment())
Самый полезный комментарий
@imrvshah Сначала обратите внимание, что
создает новый момент с текущим временем, форматирует его как строку и передает эту строку в
isSameOrAfter()
, который снова анализирует ее. Вы должны были просто сказать:И сохранил момент -> строка -> момент работы. Это намного лучший код, но я уверен, что он исправляет ошибку. Вы заметили предупреждения об устаревании, в которых говорится: «Эй, вы не должны передавать строки в такой момент»? Moment знает, как разбирать строки ISO 8601, например
moment("1982-05-25")
. Он также знает, как анализировать строки, в которых указан формат, напримерmoment("05-25-1982", "MM-DD-YYYY")
. Но он понятия не имеет, что строка типа «05-25-1982» должна быть «ММ-ДД-ГГГГ» без вашего ведома. Таким образом, он позволяет браузеру угадывать, просто передав эту строку конструкторуDate
. Другими словами, ваш код разворачивается следующим образом:Есть причина, по которой мы отказались от этого: он дает противоречивые результаты в зависимости от того, в каком браузере он запущен. Итак, вы столкнулись с тем, что iOS изначально не поддерживает этот формат. В моей консоли разработчика Safari:
Это дало вам плохие сравнения, оставившие вас с пустым массивом.