Moment: isSameOrAfter memberikan output acak saat membandingkan moment() dengan moment()

Dibuat pada 21 Feb 2017  ·  4Komentar  ·  Sumber: moment/moment

Keterangan
Jadi, saya dan seorang rekan menemukan bug dalam kode kami yang ternyata disebabkan oleh kami menggunakan variabel yang tidak ditentukan (pada dasarnya moment(undefined) dan kemudian mencoba membandingkannya dengan instance momen baru ( moment() ) dengan metode isSameOrAfter .

Jadi apa yang pada dasarnya kami gunakan, adalah ini:

let isSame = moment(undefined).isSameOrAfter(moment());

Menjalankan kode itu sekali atau dua kali akan mengembalikan true , tetapi tidak selalu. Sesekali ia mengembalikan false , saya kira itu karena membuat dua contoh momen, setelah satu sama lain, tanpa waktu yang ditentukan dapat membuatnya dengan perbedaan beberapa mikrodetik.

Berikut adalah tes yang saya jalankan di Node v7.1.0 pada Windows 10 dan di Chrome/56.0.2924.87 dengan 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();

Dua fungsi pertama akan mencatat false beberapa kali dari 1000, dan fungsi ketiga tidak. Itu hanya log ketika datang atas pengecualian.

Lingkungan:
Sel 21 Feb 2017 14:36:06 GMT+0100 (Waktu Standar Eropa Barat)
21-02-2017 14:36:06
-60
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, seperti Gecko) Chrome/56.0.2924.87 Safari/537.36
2.17.1

Komentar yang paling membantu

@imrvshah Pertama perhatikan itu

...isSameOrAfter(moment().format('MM-DD-YYYY'))

membuat momen baru dengan waktu saat ini, memformatnya sebagai string, dan meneruskan string itu ke isSameOrAfter() , yang menguraikannya lagi. Anda seharusnya baru saja mengatakan:

...isSameOrAfter(moment())

Dan simpan momen -> string -> momen kerja. Itu kode yang jauh lebih baik, tetapi saya juga yakin itu memperbaiki bug. Pernahkah Anda memperhatikan peringatan penghentian yang mengatakan "hei, Anda tidak seharusnya memberikan string ke momen seperti itu"? Saat tahu cara mengurai string ISO 8601 seperti moment("1982-05-25") . Ia juga tahu cara mengurai string di mana formatnya ditentukan, seperti moment("05-25-1982", "MM-DD-YYYY") . Tetapi ia tidak tahu bahwa string seperti "05-25-1982" dimaksudkan sebagai "MM-DD-YYYY" tanpa Anda memberi tahu. Jadi ini memungkinkan browser menebak hanya dengan menyerahkan string itu ke konstruktor Date . Dengan kata lain, kode Anda terbuka seperti ini:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

Ada alasan mengapa kami tidak menggunakannya: ini memberikan hasil yang tidak konsisten berdasarkan browser apa yang menjalankannya. Jadi yang Anda hadapi adalah iOS tidak mendukung format itu secara asli. Di konsol pengembang Safari saya:

> new Date("05-25-1982")
Invalid Date

Itu memberi Anda perbandingan buruk yang membuat Anda memiliki array kosong.

Semua 4 komentar

Mungkin saya memiliki masalah yang sama. Ini berfungsi seperti yang diharapkan pada perangkat chrome dan Android tetapi tidak di iOS.

let arrDates: Array<String> = []; _.each(Dates, (date) => { if (moment(date).isSameOrAfter(moment().format('MM-DD-YYYY'))) { arrDates.push(date); } });

di iOS saya mendapatkan array null saat bekerja di chrome dan Android.

Lingkungan:

Cordova CLI: 6.4.0
Versi Kerangka Ionik: 2.0.0
Versi CLI Ionik: 2.1.18
Versi Lib Aplikasi Ionic: 2.1.9
Versi Skrip Aplikasi Ionic: 1.0.0
versi penyebaran ios: 1.9.0
versi ios-sim: 5.0.13
OS: macOS Sierra
Versi Node: v6.9.2
Versi Xcode: Xcode 8.2.1 Versi build 8C1002

@ErikMartensson

Saya kira itu karena membuat dua contoh momen, setelah satu sama lain, tanpa waktu yang ditentukan dapat membuatnya dengan perbedaan beberapa mikrodetik.

Ya, moment() atau moment(undefined) --yang identik--berarti sekarang . Tanggal JS memiliki resolusi milidetik, jadi jika sekarang adalah milidetik yang berbeda, yang kadang-kadang akan terjadi, satu kali setelah yang lain. AFAIK, JS tidak menentukan urutan moment().isSameOrAfter(moment()) mengevaluasi dua panggilan moment() ,. Tapi karena itu jelas harus melakukan panggilan kedua sebelum mengeksekusi isSameOrAfter() , itu tidak akan mengejutkan saya jika yang kedua dalam praktik selalu datang lebih dulu. Itu berarti bahwa jika ada perbedaan waktu, itu juga akan gagal pada bagian "atauSetelah" dari tes. Anda dapat mengonfirmasi ini dengan debugger.

Aku tidak tahu harus memberitahumu apa. Ini adalah bagaimana datetime resolusi terbatas harus bekerja; "sekarang" berarti waktu yang berbeda berdasarkan saat Anda mengatakannya.

@imrvshah Pertama perhatikan itu

...isSameOrAfter(moment().format('MM-DD-YYYY'))

membuat momen baru dengan waktu saat ini, memformatnya sebagai string, dan meneruskan string itu ke isSameOrAfter() , yang menguraikannya lagi. Anda seharusnya baru saja mengatakan:

...isSameOrAfter(moment())

Dan simpan momen -> string -> momen kerja. Itu kode yang jauh lebih baik, tetapi saya juga yakin itu memperbaiki bug. Pernahkah Anda memperhatikan peringatan penghentian yang mengatakan "hei, Anda tidak seharusnya memberikan string ke momen seperti itu"? Saat tahu cara mengurai string ISO 8601 seperti moment("1982-05-25") . Ia juga tahu cara mengurai string di mana formatnya ditentukan, seperti moment("05-25-1982", "MM-DD-YYYY") . Tetapi ia tidak tahu bahwa string seperti "05-25-1982" dimaksudkan sebagai "MM-DD-YYYY" tanpa Anda memberi tahu. Jadi ini memungkinkan browser menebak hanya dengan menyerahkan string itu ke konstruktor Date . Dengan kata lain, kode Anda terbuka seperti ini:

m.isSameOrAfter("05-25-1982");
m.isSameOrAfter(moment("05-25-1982"))
m.isSameOrAfter(moment(new Date("05-25-1982")))

Ada alasan mengapa kami tidak menggunakannya: ini memberikan hasil yang tidak konsisten berdasarkan browser apa yang menjalankannya. Jadi yang Anda hadapi adalah iOS tidak mendukung format itu secara asli. Di konsol pengembang Safari saya:

> new Date("05-25-1982")
Invalid Date

Itu memberi Anda perbandingan buruk yang membuat Anda memiliki array kosong.

@icambron

Saya setuju dengan Anda dan mencari tahu kasing di konsol itu adalah peringatan penghentian karena format tanggal.

Terima kasih atas komentar Anda tentang tidak membungkusnya beberapa kali dan hanya menggunakan. ...isSameOrAfter(moment())

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

vbullinger picture vbullinger  ·  3Komentar

danieljsinclair picture danieljsinclair  ·  3Komentar

Shoroh picture Shoroh  ·  3Komentar

chitgoks picture chitgoks  ·  3Komentar

benhathaway picture benhathaway  ·  3Komentar