Moment: دعم المدد غير الصالحة

تم إنشاؤها على ٢٨ يوليو ٢٠١٤  ·  44تعليقات  ·  مصدر: moment/moment

لا توجد طريقة حاليًا لتحديد ما إذا كان تحليل المدة ناجحًا ، حتى عن طريق فحص الحقول.

New Feature

التعليق الأكثر فائدة

هل هناك أي تحديثات على هذا؟

باستخدام moment 2.23.0 ترجع الدالة isValid() أيضًا true عند محاولة إنشاء مدة من سلسلة ISO8601 غير صالحة.

مثال:

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

انها نوعا ما مزعج المنظمة البحرية الدولية. ويتجاهل تمامًا الغرض من الدالة isValid() على كائنات Duration (هل توجد حتى حالة ، عندما يقوم isValid() بإرجاع false منذ اللحظة لا تفسر حتى شيئًا غير صالح إدخال؟)

ال 44 كومينتر

أنا موافق. نحتاج إلى طريقة isValid كبداية.

أعتقد أن الفترات غير الصالحة يجب أن تلقي استثناءات وأن المعالجة الحالية للفترات غير الصالحة هي خطأ وليست تحسينًا. ضع في اعتبارك هذه الحالات:

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

ماذا ستكون النتيجة؟ لا تحدد المستندات ما يحدث عند الإدخال السيئ.

هذا له تأثير متتالي ، حيث يتم استخدام duration بدلاً من add() و subtract() ، لذلك فإن هذه السلوكيات لها سلوك غير محدد أيضًا:

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

من الاختبار اليدوي يمكنني إخبارك بما يحدث: moment "نجح" باستخدام مدة صفر.

إذا كان moment() قد ألقى ببساطة استثناء على الإدخال السيئ ، لكان من الممكن تحديد هذه المشكلة على الفور. نظرًا لأنه "نجح" بصمت ، استمر خطأ فئة Garbage-In و Garbage-Out.

نظرًا لأن سلوك المدة المطبعية غير محدد حاليًا ، فإن البدء في طرح استثناءات على السلاسل السيئة سيكون متوافقًا مع الإصدارات السابقة.

إذا تم استخدام سلسلة غير موثوق بها والتي قد تحتوي على خطأ إملائي ، فيمكن استخدام try/catch بشكل صريح عند اختبار ما إذا كان يمكن استخدام السلسلة لوصف مدة صالحة.

+1markstos.

ماذا عن دعم خيار strict (مثل اللحظة نفسها للتواريخ) الذي يلقي؟ إرجاع مدة صفر عند فشل التحليل أمر خطير للغاية.

سيكون الخيار strict أفضل من عدم التغيير ، لكنني لا أعتقد أن تحليل التواريخ غير الصالحة لأن المدة الصفرية هو سلوك افتراضي جيد في المقام الأول.

متفق. هل سيصل التغيير المحتمل فقط مع

لماذا لا تستخدم نفس النمط مثل بقية اللحظة؟ لديك حقل _isValid وطريقة isValid () وقم بتعيين المدة على أنها غير صالحة إذا فشل التحليل.

كمرجع ، فيما يلي الأماكن الموثقة الأخرى حيث يتم استخدام isValid ():

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

كان الارتباط بالوثائق وليس الرمز مقصودًا ، على الرغم من أن الكود مذكور ذو صلة أيضًا.

+1
هناك حاجة شديدة للقدرة على معرفة ما إذا كان التحليل ناجحًا أم لا.
إذا كان التوافق مع الإصدارات السابقة يمثل مصدر قلق ، فقد يكون من الممكن تقديم طريقة Duration.parse(input: string, strict?: boolean = true): Duration والتي ستظهر إذا كان الإدخال غير صحيح وتم تحديد وسيطة strict .
السلوك الحالي عندما نحصل على المدة مع جميع الأصفار للبيانات التعسفية غريب جدًا.

+1
سيكون وجود طريقة isValid () على مدة (لمعرفة ما إذا كان التحليل ناجحًا) أمرًا مفيدًا

مرحبًا بالجميع ، أصبح لدى .isValid للمدد الزمنية. ومع ذلك ، فهو متساهل جدًا. markstostheazureshadow وآخرين ، وأخبرنا إذا كان لديك اقتراحات.

marwahaha @ ،

كاختبار أولي ، قمت بنسخ / لصق أحد الأمثلة أعلاه. بدلاً من إرجاع صواب أو خطأ كما هو متوقع ، فإنه يطرح استثناء (مع اللحظة 2.18.0):

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

(لا تزال المدة غير الصالحة التي تم إنشاؤها "تنجح" دون طرح استثناء ، ولكن التحقق الآن لمعرفة ما إذا كانت المدة صالحة يطرح استثناء!)

على الرغم من عدم وجود مستندات للطريقة الجديدة حتى الآن ، لذلك ربما لم يكن هذا هو الاستخدام المقصود.

markstos لقد قمت للتو بتشغيل هذا الرمز في وحدة تحكم موقع Momentjs.com - الذي يحتوي على 2.18.0 - بدون مشكلة. هل يمكننا الحصول على مزيد من التفاصيل حول ذلك؟

ربما ، يجب أن يكون هذا الرمز غير صالح لأن الدقائق مكتوبة بشكل خاطئ.

في 21 آذار (مارس) 2017 الساعة 2:35 مساءً ، كتبت "ماجي بينت" [email protected] :

markstos https://github.com/markstos لقد قمت للتو بتشغيل هذا الرمز في ملف
وحدة التحكم في Momentjs.com - التي تحتوي على 2.18.0 - بدون مشكلة. هل يمكن ان نحصل
مزيد من التفاصيل حول ذلك؟

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288176838 ، أو كتم الصوت
الخيط
https://github.com/notifications/unsubscribe-auth/ACbGmWIf24KlRs8oiS2wTn206iJNMod7ks5roBhfgaJpZM4CRuVM
.

maggiepintmarwahaha نعم ، الخطأ الإملائي في "minutes" هو سبب عدم صلاحية المدة.

markstos لا يمكنني إعادة إنتاج هذا الاستثناء في وحدة تحكم موقع Momentjs.com أيضًا. (هذا هو 2.18.1 الآن ، على الرغم من ذلك). إذا كان لا يزال بإمكانك إعادة إنتاج الاستثناء عند الاتصال بـ isValid ، فهل يمكننا الحصول على مزيد من التفاصيل؟

screen shot 2017-03-22 at 10 38 06

(من الواضح أن مارك أراد أن يقوم isValid بإرجاع false في هذه الحالة ، لكن هذه مشكلة منفصلة عن الاستثناء. ليس واضحًا بالنسبة لي كيف يجب أن نتعامل مع تحليل الصلاحية مع مدخلات الكائن.)

لا يمكنني إعادة إنتاج الاستثناء مع 2.18.1. ربما كان إنذارًا كاذبًا. أنا يمكن أن تتكاثر نتيجةbutterflyhug الصورة من وجود هذا النوع من مدة غير صالحة عودة "صحيح" ل "isValid ()".

ألا يجب أن يفشل التحليل في هذه الحالة بدلاً من إرجاع "0 دقيقة" كناتج غير صحيح كنتيجة؟

يجب أن يكون سؤالًا مختلفًا ، لكن ما يفعله IIRC هو تفسير ذلك
القيمة بالمللي ثانية لأن الوحدة غير موجودة في وحدة التجزئة.

هل يجب أن تكون غير صالحة؟ ربما IMO.

في 22 آذار (مارس) 2017 الساعة 8:42 صباحًا ، كتب "مارك ستوسبرغ" [email protected] :

لا يمكنني إعادة إنتاج الاستثناء مع 2.18.1. ربما كان خطأ
إنذار. أنا يمكن أن تتكاثرbutterflyhug https://github.com/butterflyhug الصورة
نتيجة لوجود هذا النوع من المدة غير الصالحة بإرجاع "true" لـ
"صالح()".

لا ينبغي أن يفشل التحليل في هذه الحالة بدلاً من إرجاع "0 دقيقة" كملف
الناتج صحيح خطأ كنتيجة؟

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/moment/moment/issues/1805#issuecomment-288440827 ، أو كتم الصوت
الخيط
https://github.com/notifications/unsubscribe-auth/AFxi0nZAz8gwAJM8fVx5rYPyIWjeEfHMks5roUF4gaJpZM4CRuVM
.

يبدو أن هناك خطأ هنا:

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

يتم افتراض أن السلسلة صالحة وتظهر في خريطة "المدة". يبدو أن الإصلاح هو إضافة فحص هنا لتأكيد أن السلسلة قيمة صالحة لتعيينها. إذا لم يكن كذلك ، فقم بتعيين _isValid:false

يتوافق هذا السلوك مع الطريقة القياسية isValid :

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

مصدر هذا هو normalizeObjectUnits https://github.com/moment/moment/blob/497f918515ae6ab900f008f19523b1e4ae5e2450/src/lib/units/aliases.js#L14 -L29 الذي يضيف فقط سمات صالحة (ويسقط المخالف منها).

maggiepintichernev هل يجب تغيير هذا السلوك؟ نحن بصدد إصدار جديد قريبًا ...

يعد تحويل '3 دقائق' إلى '0 دقيقة' وإعلان النتيجة "صالحة" خطأ. قد يكون تغييرًا جذريًا لإصلاحه ، لكنه لا يزال إصلاحًا للخلل.

أوافق على أن سلوك التحقق هذا ليس مثاليًا ، لكنني لا أوافق على أن هذا خطأ بالضرورة.

ضع في اعتبارك الحالة التي تقوم فيها بتحليل شيء مثل moment({'minutes': 3, '$cacheKey': 92619502}).isValid() . أتوقع بشدة أن لدينا مستخدمين يقدرون وجود هذا التحليل كلحظة صالحة ، ولا أرى تمييزًا مبدئيًا بين هذا المثال والخطأ الذي كتبته.

واجهة برمجة التطبيقات التي نناقشها هي "محلل الكائن" لمُنشئ moment ، وهو موثق هنا:

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

الوثائق صامتة حاليًا بشأن معالجة تمرير الحجج غير المعروفة أو الإضافية.

في الوقت الحالي ، يمكن وصف سلوك Moment هنا بأنه "إدخال قمامة ، إخراج قمامة". يتم قبول الإدخال غير المرغوب فيه بصمت والنتيجة هي "غير موجودة" - يتم تحويل التواريخ التي بها أخطاء إملائية إلى تواريخ أخرى وتعتبر صالحة!

ستتيح هذه التحديثات للمطور اكتشاف خطأ في أقرب وقت ممكن:

  • يتم تمرير المستند إلى أنه سيتم طرح استثناء في وسيطات غير معروفة إلى مُنشئ الكائن.

    • قم بطرح استثناء إذا تم تمرير وسيطات غير معروفة إلى مُنشئ الكائن

وطالما استمرت Moment في قبول "Garbage In" على أنها صالحة ، فستظل تُلحق الضرر بالمطورين وسيُترك المستخدمون مع تقرير Moment بشكل خاطئ بأن التواريخ المعطلة "صالحة".

يبدو أن هذا التحسن يستحق تغييرًا "متقطعًا".

لقد تعرضت للعض من هذا: moment().subtract('1 day') ... هذه ليست طريقة صالحة للتعبير عن المدة. لا أتوقع أن يكون ما يعادل .subtract(0) رغم ذلك. IMO ، الشيء الأقل إثارة للدهشة في هذه الحالة هو الرمي.

johnvh أوافق تمامًا.

أنت تعلم أنها ليست "طريقة صالحة للتعبير عن المدة" ولكنك تكتب هذا الرمز على أي حال؟ ماذا تتوقع؟ أفترض أنك استنتجت أنها ليست طريقة صالحة للتعبير عن المدة من لحظة التوثيق الممتازة التي يوفرها المؤلفون؟

في 25/04/2017 ، الساعة 08:29 ، كتب Mark Stosberg [email protected] :

johnvh أوافق تمامًا.

-
أنت تتلقى هذا لأنك مشترك في هذا الموضوع.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

simonfox المطورين هم بشر. نحن نرتكب اخطاء. هذا هو السبب في أن نصف قاعدة الكود لدينا عبارة عن اختبارات. توثيق اللحظة / هو / ممتاز ، لكنه لا يساعد إذا كنت تعتقد أنك تذكرت واجهة برمجة التطبيقات بشكل صحيح ولا تحتاج إلى الرجوع إلى الوثائق. هذا هو السبب في أنه من المفيد ليس فقط الحصول على وثائق رائعة ولكن أيضًا رمز فشل عند إدخال غير صالح بدلاً من تحويل الإدخال غير الصحيح بصمت إلى إدخال "صالح" معطوب. إذا كان johnvh قد تلقى على الفور فشلًا في التحقق من الصحة عند تشغيل الكود الخاص به ، فقد يكون قد تحقق من الوثائق الممتازة لمعرفة ما قد تكون المشكلة. لسوء الحظ ، تعاملت Moment مع الإدخال غير الصحيح على أنه صالح ورفعت دون إنذار.

markstos بالضبط. أوافق 100٪.

كان هذا خطأ يجب تعقبه. لم نكتبها بهذه الطريقة مع العلم أنها كانت غير صالحة بالطبع. يبدو الأمر صحيحًا ، لأن أساليب التلاعب باللحظة متحررة جدًا في التوقيعات المدعومة. نستخدم أيضًا جدول الأعمال في نفس المشروع ، والذي يستخدم الفاصل الزمني البشري لتحويل اللغة الطبيعية إلى فترات. لذلك سيكون لدينا شيء مثل هذا فقط خطوط متباعدة:

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

هذا الأخير يعمل على النحو المنشود ، والأول لا يعمل. إذا أثار الأول استثناء ، لكان قد نبهنا إلى خطأنا.

أيضًا ، تشير حقيقة أن Moment / has / an isValid () إلى أنها تتحقق من صحة القيم على أنها إما صالحة أو غير صالحة. في الحالات التي يتم فيها تصنيف القيم غير الصالحة على أنها صالحة ، يبدو أن طريقة isValid() لا تعمل كما هي موثقة.

مرحبًا بالجميع ، نود مراجعة أي علاقات عامة في هذه المنطقة!

واجهت هذا الخطأ ، أو شيء مشابه له. إذا قمت بتشغيل moment.duration('3', 'minutes').asMinutes() باستخدام Moment 2.18.1 ، فسأحصل على النتيجة 0. أعتقد أنه يجب إما إرجاع 3 أو طرح استثناء. على الأقل ، يجب أن يُرجع false moment.duration('3', 'minutes').isValid() false .

الطريقة التي تتصرف بها Moment الآن يمكن أن تسبب الكثير من المتاعب من خلال التسبب في أخطاء قد يكون من الصعب اكتشافها وتشخيصها ، كما ذكر العديد من الأشخاص هنا.

هل تم معالجة هذا؟

TomJSmith يظهر اختبار سريع أن الخطأ لا يزال موجودًا. هذا الرمز:

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

"تنجح" ، بطرح صفر أيام بدلاً من يوم واحد كما هو متوقع. يمكنك استدعاء .isValid() في التاريخ الناتج والحصول على استجابة true تشير إلى أن النتيجة صحيحة عندما لا تكون كذلك.

قد يؤدي السلوك الحالي إلى عواقب وخيمة في بعض حالات الاستخدام ويجب توثيقه بوضوح مع تحذير:

حالة الاستخدام
أرغب في حذف الموارد بناءً على مدة الاحتفاظ:

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

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

نتيجة:

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

عاقبة:
يتم حذف كل الموارد حتى التاريخ الحالي ...

حتى الآن ، الطريقة الوحيدة التي وجدتها لحل هذا إذا قمت باختبار القيمة بعد التحليل:

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

نعم ، هذا الخطأ سيء وقد تم فتحه منذ عام 2014. هذا شيء تصححه مشاريع "date-fns". يخبرونك في الواقع إذا كان الإدخال غير صالح غير صالح. https://date-fns.org/ لسوء الحظ ، لا يتعامل date-fns مع تحويلات المنطقة الزمنية ، ولكن ربما توجد طريقة للتعامل مع تلك التي تحتوي على مكتبة خارجية.

لكي يقوم مشروع Moment بإصلاح ذلك ، يتعين عليهم إنهاء قبول الإدخال المهمل ومعاملته على أنه تاريخ صالح. على الرغم من أن هذا يبدو سلوكًا أفضل ، إلا أنه تقنيًا تغيير "السلوك الانكساري إلى الوراء" ، لذلك يبدو أن هناك مقاومة لإجراء التغيير. ولكن نظرًا لأن المشروع لم يتخذ إجراءات في السنوات الأربع الماضية تقريبًا ، فلن أتوقع إصلاحًا قريبًا.

هل هناك أي تحديثات على هذا؟

باستخدام moment 2.23.0 ترجع الدالة isValid() أيضًا true عند محاولة إنشاء مدة من سلسلة ISO8601 غير صالحة.

مثال:

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

انها نوعا ما مزعج المنظمة البحرية الدولية. ويتجاهل تمامًا الغرض من الدالة isValid() على كائنات Duration (هل توجد حتى حالة ، عندما يقوم isValid() بإرجاع false منذ اللحظة لا تفسر حتى شيئًا غير صالح إدخال؟)

robbiecloset التحديث منذ آخر مشاركة لي في أبريل ، تحسن مشروع "date-fns" في دعم المنطقة الزمنية. هناك الآن مشاريع "date-fns-timezone" و "date-fns-tz" للمساعدة في ذلك.

سأفكر في استخدامه إذا كان من الممكن التبديل.

أنا أستخدم moment.duration(value).toISOString() === value ، تتم قراءة هذه القيمة من التكوين.

أستخدم Moment.duration (value) .toISOString () === القيمة ، تتم قراءة هذه القيمة من التكوين.

@ bors-ltd أعتقد أن جزءًا من المشكلة هو أن هذه اللحظة قد تكون قادرة على فك تشفير قيمتين تنتجان نفس القيمة المشفرة.

على سبيل المثال: moment.duration('PT0M0S').toISOString() === moment.duration('PT0S').toISOString() .

إذا نظرت إلى الاختبارات ، يبدو أن القيم غير الصالحة هي في الواقع منفصلة عن المواصفات:

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

يتم اختبار الأنماط التي لا تتطابق مع معيار مدة ISO على أنها "0" ثانية.

مرحبًا ، لقد واجهنا أيضًا نفس المشكلة مع طريقة isValid() وانتهى بنا الأمر للقيام بذلك يدويًا.
const isValidDuration = duration => { return !!duration.match( /^(-?)P(?=\d|T\d)(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)([DW]))?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ ); };
أتمنى أن يساعد أي شخص.

راجع https://momentjs.com/docs/#/ -project-status /

شكرا لكل المناقشة هنا.

إصلاح الاختراق هو استبدال طريقة isValid بطريقة تضمن أن مجموع أجزاء البيانات> 0 (أو على الأقل غير صالح على الأقل)

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات