Moment: Mendukung durasi yang tidak valid

Dibuat pada 28 Jul 2014  ·  44Komentar  ·  Sumber: moment/moment

Saat ini tidak ada cara untuk menentukan apakah penguraian durasi berhasil, bahkan dengan memeriksa bidang.

New Feature

Komentar yang paling membantu

Apakah ada pembaruan tentang ini?

Dengan moment 2.23.0 fungsi isValid() juga mengembalikan true ketika mencoba membuat durasi dari string ISO8601 yang tidak valid.

Contoh:

const mom = moment.duration('asdf')
console.log(mom.isValid()) // This returns true, expected would be false 

Itu agak mengganggu imo. dan sepenuhnya mengalahkan tujuan fungsi isValid() pada objek Duration (apakah ada kasus, ketika isValid() mengembalikan false karena momen tidak menafsirkan bahkan yang tidak valid memasukkan?)

Semua 44 komentar

Saya setuju. Kami membutuhkan metode isValid sebagai permulaan.

Saya pikir durasi yang tidak valid harus membuang pengecualian dan penanganan saat ini dari durasi yang tidak valid adalah bug bukan peningkatan. Pertimbangkan kasus-kasus ini:

`var wrong = moment.duration(3,'mintues');`

Apa hasilnya? Dokumen tidak mendefinisikan apa yang terjadi pada input yang buruk.

Ini memiliki efek berjenjang, karena duration digunakan sebagai ganti add() dan subtract() , jadi ini juga memiliki perilaku yang tidak terdefinisi:

var hmm = moment().subtract(3,'mintues').toDate();
var uhoh = moment().add(3,'mintues').toDate();

Dari pengujian manual saya dapat memberitahu Anda apa yang terjadi: moment "berhasil" dengan menggunakan durasi nol.

Jika moment() hanya melemparkan pengecualian pada input yang buruk, masalah ini akan segera diidentifikasi. Karena secara diam-diam "berhasil", bug kelas Garbage-In, Garbage-Out tetap ada.

Karena perilaku durasi yang salah ketik saat ini tidak ditentukan, mulai melempar pengecualian pada string yang buruk akan kompatibel ke belakang.

Jika string yang digunakan tidak tepercaya yang mungkin memiliki kesalahan ketik, try/catch dapat digunakan secara eksplisit saat menguji apakah string dapat digunakan untuk menggambarkan durasi yang valid.

+1 @markstos.

Bagaimana dengan mendukung opsi strict (seperti momen itu sendiri untuk tanggal) yang muncul? Mengembalikan durasi nol saat parsing gagal cukup berbahaya.

Opsi strict akan lebih baik daripada tidak ada perubahan, tetapi saya tidak berpikir mem-parsing tanggal yang tidak valid karena durasi nol adalah perilaku default yang baik sejak awal.

Sepakat. Akankah perubahan yang mungkin terjadi hanya mendarat dengan [email protected]?

Mengapa tidak menggunakan pola yang sama dengan momen lainnya? Miliki bidang _isValid dan metode isValid() dan tetapkan durasi sebagai tidak valid jika penguraian gagal.

Untuk referensi, berikut adalah tempat terdokumentasi lain di mana isValid() digunakan:

https://github.com/moment/momentjs.com/search?utf8=%E2%9C%93&q=isValid

Menautkan ke dokumentasi bukan kode yang disengaja, meskipun penyebutan kode juga relevan.

+1
Kemampuan untuk mengetahui apakah parsing berhasil atau tidak sangat dibutuhkan.
Jika kompatibilitas mundur menjadi perhatian maka ada kemungkinan untuk memperkenalkan metode Duration.parse(input: string, strict?: boolean = true): Duration yang akan muncul jika input salah dan argumen strict ditentukan.
Perilaku saat ini ketika kami mendapatkan Durasi dengan semua nol untuk data arbitrer sangat aneh.

+1
Memiliki metode isValid() pada durasi (untuk melihat apakah penguraian berhasil) akan berguna

Hai semua, Momen 2.18.0 sekarang memiliki metode .isValid untuk durasi. Namun, itu cukup lunak. @markstos @theazureshadow dan lainnya, cobalah dan beri tahu kami jika Anda memiliki saran.

@marwahaha ,

Sebagai tes awal, saya copy/paste salah satu contoh di atas. Alih-alih mengembalikan benar atau salah seperti yang diharapkan, itu melempar pengecualian (dengan momen 2.18.0):

 moment.duration(3,'mintues').isValid();

(Membuat durasi yang tidak valid masih "berhasil" tanpa mengeluarkan pengecualian, tetapi sekarang memeriksa untuk melihat apakah itu valid melempar pengecualian!)

Meskipun tampaknya belum ada dokumen untuk metode baru, jadi mungkin ini bukan tujuan penggunaan.

@markstos Saya baru saja menjalankan kode itu di konsol Momentjs.com - yang memiliki 2.18.0 - tanpa masalah. Bisakah kita mendapatkan detail lebih lanjut tentang itu?

Mungkin, kode itu seharusnya tidak valid karena menit salah dieja.

Pada 21 Mar 2017 14:35, "Maggie Pint" [email protected] menulis:

@markstos https://github.com/markstos Saya baru saja menjalankan kode itu di
konsol Momentjs.com - yang memiliki 2.18.0 - tanpa masalah. Bisakah kita mendapatkan?
lebih detail tentang itu?


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288176838 , atau bisu
benang
https://github.com/notifications/unsubscribe-auth/ACbGmWIf24KlRs8oiS2wTn206iJNMod7ks5roBhfgaJpZM4CRuVM
.

@maggiepint @marwahaha Ya, salah mengeja "menit" adalah mengapa durasinya tidak valid.

@markstos Saya juga tidak dapat mereproduksi pengecualian itu di konsol Momentjs.com. (Namun, sekarang 2.18.1.) Jika Anda masih dapat mereproduksi pengecualian saat memanggil isValid, bisakah kami mendapatkan detail lebih lanjut?

screen shot 2017-03-22 at 10 38 06

(Jelas Mark ingin isValid mengembalikan false dalam situasi ini, tapi itu masalah terpisah dari pengecualian. Tidak 100% jelas bagi saya bagaimana kita harus menangani validitas parsing dengan input objek.)

Saya juga tidak dapat mereproduksi pengecualian dengan 2.18.1. Mungkin itu alarm palsu. Saya dapat mereproduksi hasil @butterflyhug karena durasi tidak valid semacam ini mengembalikan "true" untuk "isValid()".

Bukankah penguraian seharusnya gagal dalam kasus ini alih-alih mengembalikan "0 menit" sebagai hasil yang salah-valid sebagai hasilnya?

Seharusnya adalah pertanyaan yang berbeda, tetapi IIRC yang dilakukannya adalah menafsirkan itu
nilai sebagai milidetik karena unit tidak ditemukan di unit hashtable.

Haruskah itu tidak valid? IMO mungkin.

Pada 22 Maret 2017 08:42, "Mark Stosberg" [email protected] menulis:

Saya juga tidak dapat mereproduksi pengecualian dengan 2.18.1. Mungkin itu salah
alarm. Saya dapat mereproduksi @butterflyhug https://github.com/butterflyhug 's
hasil dari durasi tidak valid semacam ini yang mengembalikan "benar" untuk
"adalah benar()".

Seharusnya parsing tidak gagal dalam kasus ini alih-alih mengembalikan "0 menit" sebagai
output yang salah-valid sebagai hasilnya?


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288440827 , atau bisu
benang
https://github.com/notifications/unsubscribe-auth/AFxi0nZAz8gwAJM8fVx5rYPyIWjeEfHMks5roUF4gaJpZM4CRuVM
.

Tampaknya ada bug di sini:

https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/duration/create.js#L34

Asumsi dibuat bahwa string tersebut valid dan muncul di peta "durasi". Sepertinya perbaikannya adalah menambahkan tanda centang di sini untuk mengonfirmasi bahwa string adalah nilai yang valid untuk ditetapkan. Jika tidak, setel _isValid:false

Perilaku ini konsisten dengan metode isValid :

moment({'mintues': 3}).isValid()
> true

Sumbernya adalah normalizeObjectUnits https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/units/aliases.js#L14 -L29 yang hanya menambahkan atribut yang valid (dan menghapus pelanggaran yang).

@maggiepint @ichernev haruskah perilaku ini berubah? Kami akan segera melakukan Breaking Release...

Mengubah '3 menit' menjadi '0 menit' dan menyatakan hasil "valid" adalah bug. Ini mungkin merupakan perubahan yang melanggar untuk memperbaikinya, tetapi ini masih merupakan perbaikan bug.

Saya setuju bahwa perilaku validasi ini tidak ideal, tetapi saya tidak setuju bahwa ini adalah bug .

Pertimbangkan kasus di mana Anda mengurai sesuatu seperti moment({'minutes': 3, '$cacheKey': 92619502}).isValid() . Saya sangat berharap bahwa kami memiliki pengguna yang menghargai penguraian itu sebagai momen yang valid, dan saya tidak melihat perbedaan prinsip antara contoh ini dan bug yang Anda tulis.

API yang sedang kita diskusikan adalah "pengurai objek" untuk konstruktor moment , yang didokumentasikan di sini:

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

Dokumentasi saat ini diam tentang perlakuan melewati argumen yang tidak diketahui atau tambahan.

Saat ini, perilaku Momen di sini dapat digambarkan sebagai "Sampah Masuk, Sampah Keluar". Masukan sampah diterima secara diam-diam dan hasilnya adalah "Sampah keluar"-- tanggal yang salah eja dikonversi ke tanggal lain dan dianggap valid!

Pembaruan ini akan memungkinkan pengembang mengetahui sesegera mungkin bahwa mereka telah melakukan kesalahan:

  • Dokumen bahwa pengecualian akan dilemparkan ke dalam argumen yang tidak diketahui diteruskan ke konstruktor objek.

    • Lempar pengecualian jika argumen yang tidak diketahui diteruskan ke konstruktor objek

Selama Momen terus menerima "Sampah Masuk" sebagai valid, itu akan terus merugikan pengembang dan pengguna dibiarkan dengan Momen yang salah melaporkan bahwa tanggal yang rusak adalah "valid".

Peningkatan ini tampaknya layak untuk "melanggar" perubahan.

Saya baru saja digigit oleh ini: moment().subtract('1 day') ... ini bukan cara yang valid untuk menyatakan durasi. Saya tidak berharap itu setara dengan .subtract(0) sekalipun. IMO, hal yang paling tidak mengejutkan untuk dilakukan dalam hal ini adalah melempar.

@johnvh saya setuju sepenuhnya.

Anda tahu itu bukan "cara yang valid untuk menyatakan durasi" namun Anda tetap menulis kode itu? Apa yang kamu harapkan? Saya berasumsi Anda berhasil itu bukan cara yang valid untuk mengekspresikan durasi dari dokumentasi yang sangat baik yang disediakan oleh penulis momentjs?

Pada 25/04/2017, di 08:29, Mark Stosberg [email protected] menulis:

@johnvh saya setuju sepenuhnya.


Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub, atau matikan utasnya.

Pengembang @simonfox adalah manusia. Kami membuat kesalahan. Itu sebabnya setengah basis kode kami adalah tes. Dokumentasi Momen /is/ sangat baik, tetapi tidak membantu jika Anda yakin telah mengingat API dengan benar dan tidak perlu merujuk dokumentasi. Itulah mengapa sangat membantu untuk tidak hanya memiliki dokumentasi yang bagus tetapi juga kode yang gagal pada input yang tidak valid alih-alih secara diam-diam mengubah input yang tidak valid menjadi input "valid" yang rusak. Jika @johnvh segera menerima kegagalan validasi ketika kodenya dijalankan, dia bisa memeriksa dokumentasi yang sangat baik untuk melihat apa masalahnya. Sayangnya, Momen memperlakukan input yang tidak valid sebagai valid dan tidak mengaktifkan alarm.

@markstos tepatnya. Saya setuju 100%.

Ini adalah bug yang harus dilacak. Kami tidak menulisnya seperti itu karena tahu itu tidak valid tentu saja. Kelihatannya benar, karena metode manipulasi momen sangat liberal dalam tanda tangan yang didukungnya. Kami juga menggunakan agenda dalam proyek yang sama, yang menggunakan interval manusia untuk mengubah bahasa alami menjadi durasi. Jadi kita akan memiliki sesuatu seperti ini hanya terpisah baris:

moment().subtract('1 day');
agenda.processEvery('1 day');

Yang terakhir berfungsi sebagaimana dimaksud, yang pertama tidak. Jika yang pertama mengajukan pengecualian, itu akan mengingatkan kita akan kesalahan kita.

Juga, fakta bahwa metode Moment /has/ an isValid() menyiratkan bahwa metode tersebut memvalidasi nilai sebagai valid atau tidak valid. Dalam kasus di mana nilai yang tidak valid diklasifikasikan sebagai valid, metode isValid() tampaknya tidak berfungsi seperti yang didokumentasikan.

Hai semua, kami ingin meninjau PR apa pun di area ini!

Saya mengalami bug ini, atau yang serupa dengannya. Jika saya menjalankan moment.duration('3', 'minutes').asMinutes() menggunakan Momen 2.18.1, saya mendapatkan hasil 0. Saya pikir itu harus mengembalikan 3 atau melempar pengecualian. Setidaknya, moment.duration('3', 'minutes').isValid() harus mengembalikan false .

Cara Momen berperilaku sekarang dapat menyebabkan banyak masalah dengan menyebabkan bug yang mungkin sulit dideteksi dan didiagnosis, seperti yang disebutkan beberapa orang di sini.

Apakah ini sudah ditangani?

@TomJSmith Tes cepat menunjukkan bug masih ada. Kode ini:

 moment().subtract('1 day');

"berhasil", kurangi nol hari, bukan satu hari seperti yang diharapkan. Anda dapat menelepon .isValid() pada tanggal yang dihasilkan dan mendapatkan balasan true menunjukkan bahwa hasilnya valid padahal tidak.

Perilaku saat ini dapat menyebabkan konsekuensi buruk dalam beberapa kasus penggunaan dan harus didokumentasikan dengan jelas dengan peringatan:

Kasus penggunaan
Saya ingin menghapus sumber daya berdasarkan durasi retensi:

const duration = moment.duration('invalid');
const currentDate = moment();
const removeBeforeDate  = moment().subtract(duration);

console.log(`currentDate      : ${currentDate}`);
console.log(`removeBeforeDate : ${removeBeforeDate}`);

Hasil:

currentDate      : Fri Apr 13 2018 13:15:04 GMT+0200
removeBeforeDate : Fri Apr 13 2018 13:15:04 GMT+0200

Konsekuensi:
Setiap sumber daya hingga tanggal saat ini dihapus...

Sejauh ini, satu-satunya cara saya menemukan solusi ini jika menguji nilai setelah penguraian:

const duration = moment.duration('invalid');
if (duration.toISOString() === 'P0D') {
    // throw an Error
}

Ya, bug ini buruk dan telah dibuka sejak 2014. Ini adalah sesuatu yang diperbaiki oleh proyek "date-fns". Mereka benar-benar memberi tahu Anda jika input yang tidak valid tidak valid. https://date-fns.org/ Sayangnya, date-fns tidak menangani konversi zona waktu, tetapi mungkin ada cara untuk menanganinya dengan perpustakaan eksternal.

Untuk proyek Moment untuk memperbaikinya, mereka harus berhenti menerima input sampah dan memperlakukannya sebagai tanggal yang valid. Meskipun ini tampak seperti perilaku yang lebih baik, secara teknis ini adalah perubahan "perilaku melanggar mundur", jadi tampaknya ada penolakan untuk melakukan perubahan. Tetapi mengingat proyek tersebut tidak mengambil tindakan dalam hampir empat tahun terakhir, saya tidak akan mengharapkan perbaikan segera.

Apakah ada pembaruan tentang ini?

Dengan moment 2.23.0 fungsi isValid() juga mengembalikan true ketika mencoba membuat durasi dari string ISO8601 yang tidak valid.

Contoh:

const mom = moment.duration('asdf')
console.log(mom.isValid()) // This returns true, expected would be false 

Itu agak mengganggu imo. dan sepenuhnya mengalahkan tujuan fungsi isValid() pada objek Duration (apakah ada kasus, ketika isValid() mengembalikan false karena momen tidak menafsirkan bahkan yang tidak valid memasukkan?)

@robbiecloset Pembaruan sejak posting terakhir saya di bulan April, proyek "date-fns" menjadi lebih baik pada dukungan zona waktu. Sekarang ada proyek "date-fns-timezone" dan "date-fns-tz" untuk membantu dalam hal ini.

Saya akan mempertimbangkan untuk menggunakannya jika layak untuk beralih.

Saya menggunakan moment.duration(value).toISOString() === value , nilai itu dibaca dari konfigurasi.

Saya menggunakan nilai moment.duration(value).toISOString() ===, nilai itu dibaca dari konfigurasi.

@bors-ltd Saya pikir bagian dari masalahnya adalah saat itu mungkin dapat memecahkan kode dua nilai yang menghasilkan nilai yang disandikan yang sama.

Misalnya: moment.duration('PT0M0S').toISOString() === moment.duration('PT0S').toISOString() .

Jika Anda melihat tes, sepertinya nilai yang tidak valid sebenarnya terlepas dari spesifikasi:

https://github.com/moment/moment/blob/2.24.0/src/test/moment/duration.js#L419 -L420

Pola yang tidak sesuai dengan standar durasi ISO sedang diuji sebagai "0" detik.

Halo, kami juga memiliki masalah yang sama dengan metode isValid() dan akhirnya melakukannya secara manual.
const isValidDuration = duration => { return !!duration.match( /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ ); };
Semoga bisa membantu siapa saja.

Lihat https://momentjs.com/docs/#/ -project-status/

Terima kasih untuk semua diskusi di sini.

Perbaikan hacky adalah mengganti metode isValid dengan metode yang memastikan bahwa jumlah bagian data > 0 (atau setidaknya kemungkinan tidak valid)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat