Moment: ينتج عن حساب الحد الأدنى للعمر بقيم عيد ميلاد الحدود سلوك غير متوقع

تم إنشاؤها على ٢٧ فبراير ٢٠١٧  ·  3تعليقات  ·  مصدر: moment/moment

وصف المشكلة وخطوات إعادة الإنتاج

أريد أن أتحقق مما إذا كان الشخص بالغ الصغر أو يزيد عمره عن 18 عامًا. لذلك استخدمت الدالتين diff() و duration() لحساب عمر الشخص. لقد كتبت بعض الاختبارات بقيم الحدود لاختبار منطقي. كنت أرغب في اختبار ما إذا كان عمري أقل من 18 عامًا بالضبط في يوم واحد و 18 عامًا بالضبط. لذلك اخترت عيد ميلاد للاختبار (اليوم 27.02.2017):

  • بالضبط 18: 27.02.1999
  • يوم واحد أقل من 18 سنة: 28.02.1999

إعادة إنتاج

// today date is: 27.02.2017

// exactly age 18    
var birthday = moment("27.02.1999", "DD.MM.YYYY"),
    age = moment.duration(moment().diff(birthday)).asYears();

      console.log(age); // output: 18.00325100985672; expected: == 18

// one day under age 18
var birthday = moment("28.02.1999", "DD.MM.YYYY"),
    age = moment.duration(moment().diff(birthday)).asYears();

    console.log(age); // output: 18.00053005036735; expected: < 18

أعتقد أن الحساب صحيح ، بسبب السنوات الكبيسة. لكن فيما يتعلق بعيد الميلاد ، يجب ألا يكون عمر الشخص 18 عامًا. ربما هناك طريقة أخرى للقيام بذلك باستخدام Momjs وأنا أفعل ذلك بشكل خاطئ. إذا كان الأمر كذلك ، فسيكون من الجيد ذكرها في توثيق Moments.

رمز الإنتاج

<form id="newsletter-form" data-parsley-validate="">
  <input id="birthday" type="text" class="form-control" required="" data-parsley-minage="18">
  <input type="submit" class="btn btn-default" value="subscribe">
</form>

<script type="text/javascript">
    $(function () {
        window.Parsley.addValidator('minage', {
            validateString: function(value, minAge) {
                var birthday = moment(value, "DD.MM.YYYY"),
                    age = moment.duration(moment().diff(birthday)).asYears();

                return (age >= minAge);
            },
            requirementType: 'integer',
            messages: {
                en: 'You must be mature.'
            }
        });
    });
</script>
<script type="text/javascript">
    $(function () {
        $('#newsletter-form').parsley()
            // field validation
            .on('form:submit', function() {
                return false; // do not submit
            });
    });
</script>

بيئة

إصدار Chrome 56.0.2924.87 (64 بت) على Windows 7

معلومات أخرى قد تكون مفيدة

  • المنطقة الزمنية للجهاز: "(UTC + 01: 00) أمستردام ، برلين ، برن ، روم ، ستوكهولم ، فيينا"
  • وقت وتاريخ تشغيل الرمز: "الاثنين 27 فبراير 2017 13:38:04 GMT + 0100"
  • المكتبات الأخرى المستخدمة: jquery-3.1.1 ، bootstrap-3.3.7 ، bootstrap-datepicker-1.6.4 ، parselyjs-2.6.2
console.log( (new Date()).toString()) // Mon Feb 27 2017 13:38:04 GMT+0100 (Mitteleuropäische Zeit)
console.log((new Date()).toLocaleString()) // 27.2.2017, 13:38:04
console.log( (new Date()).getTimezoneOffset()) // -60
console.log( navigator.userAgent) // Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
console.log(moment.version) // 2.17.1

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

هل تعمل بشكل أفضل إذا كنت تستخدم فقط

age = moment().diff(birthday, 'years');

ال 3 كومينتر

أعتقد أن الحساب خاطئ ، لكنه قريب جدًا . ربما بسبب أخطاء التقريب؟

على سبيل المثال:

a = moment("27.02.1999", "DD.MM.YYYY");
b = moment("28.02.1999", "DD.MM.YYYY");
c = moment("27.02.2017", "DD.MM.YYYY");
moment.duration(c.diff(a)).asYears(); // 18.00173857094944
moment.duration(c.diff(b)).asYears(); // 17.99900066394245

لذلك ، في هذه الحالة ، سيعود moment.duration(end.diff(start)).asYears() 18 قبل 16 ساعة تقريبًا من ذلك.

إذا كنت تحاول التحقق مما إذا كان العمر أكبر من 18 عامًا أو يساويها ، فيمكنك مقارنة السنوات ، ثم (إذا كانت هناك 18 عامًا متباعدة) بين الأشهر ، ثم الأيام.

// pseudocode, correctness not guaranteed
function is18(start, end) {
  if (end.year() - start.year() == 18) {
    if (end.month() == start.month()) {
      return end.date() >= start.date();
    }
    return end.month() > start.month();
  }
  return end.year() - 18 > start.year();
}

هل تعمل بشكل أفضل إذا كنت تستخدم فقط

age = moment().diff(birthday, 'years');

@ mj1856

يا ، هذا يعمل بشكل جيد.

// today date is: 03.03.2017

// exactly age 18    
var birthday = moment("03.03.1999", "DD.MM.YYYY"),
    age = moment().diff(birthday, 'years');

      console.log(age); // output: 18; expected: == 18

// one day under age 18
var birthday = moment("04.03.1999", "DD.MM.YYYY"),
    age = moment().diff(birthday, 'years');

    console.log(age); // output: 17; expected: < 18
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات