Moment: Perhitungan usia minimal dengan nilai ulang tahun batas menghasilkan perilaku yang tidak terduga

Dibuat pada 27 Feb 2017  ·  3Komentar  ·  Sumber: moment/moment

Deskripsi Masalah dan Langkah-langkah untuk Mereproduksi

Saya ingin memeriksa apakah seseorang berusia tepat atau lebih dari 18 tahun. Jadi saya menggunakan fungsi diff() dan duration() untuk menghitung usia seseorang. Saya menulis beberapa tes dengan nilai batas untuk menguji logika saya. Saya ingin menguji apakah saya tepat satu hari lebih muda dari 18 tahun dan tepat 18 tahun. Jadi saya memilih dua hari ulang tahun untuk pengujian (hari ini 27.02.2017):

  • tepatnya 18: 27.02.1999
  • satu hari di bawah 18: 28.02.1999

Reproduksi

// 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

Saya pikir perhitungannya benar, karena tahun kabisat. Tetapi dalam hal ulang tahun, orang tersebut tidak boleh berusia 18 tahun. Mungkin ada cara lain untuk melakukannya dengan momentjs dan saya salah melakukannya. Jika demikian, alangkah baiknya disebutkan dalam dokumentasi momentjs.

Kode Produksi

<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>

Lingkungan

Chrome Versi 56.0.2924.87 (64-bit) di Windows 7

Informasi lain yang mungkin bermanfaat

  • Zona waktu mesin: "(UTC+01:00) Amsterdam, Berlin, Bern, Rom, Stockholm, Wien"
  • Waktu dan tanggal saat kode dijalankan: "Senin 27 Februari 2017 13:38:04 GMT+0100"
  • Pustaka lain yang digunakan: 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

Komentar yang paling membantu

Apakah itu bekerja lebih baik jika Anda hanya menggunakan

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

Semua 3 komentar

Saya pikir perhitungannya salah, tetapi sangat dekat. Mungkin karena kesalahan pembulatan?

Sebagai contoh:

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

Jadi, dalam hal ini, moment.duration(end.diff(start)).asYears() akan mengembalikan 18 sekitar 16 jam sebelum seharusnya.

Jika Anda mencoba memeriksa apakah usia lebih dari atau sama dengan 18, Anda dapat membandingkan tahun, lalu (jika berbeda 18 tahun) bulan, lalu hari.

// 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();
}

Apakah itu bekerja lebih baik jika Anda hanya menggunakan

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

@mj1856

Ya, ini bekerja dengan baik.

// 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
Apakah halaman ini membantu?
0 / 5 - 0 peringkat