How to check if a given Date exists in DART?

6,580

Solution 1

You can convert parsed date to string with original format and then compare if it's matching the input.

void main() {
  var inputs = ['20180101', // -> 2018-01-01 00:00:00.000
                '20181231', // -> 2018-12-31 00:00:00.000
                '20180230', // -> 2018-03-02 00:00:00.000
                '20181301', // -> 2019-01-01 00:00:00.000
                '20181364'];// -> 2019-03-05 00:00:00.000

  inputs.forEach((input) {
    print("$input is valid string: ${isValidDate(input)}");
  });
}

bool isValidDate(String input) {
  final date = DateTime.parse(input);
  final originalFormatString = toOriginalFormatString(date);
  return input == originalFormatString;
}

String toOriginalFormatString(DateTime dateTime) {
  final y = dateTime.year.toString().padLeft(4, '0');
  final m = dateTime.month.toString().padLeft(2, '0');
  final d = dateTime.day.toString().padLeft(2, '0');
  return "$y$m$d";
}

Solution 2

My solution to validate the birthday was this, we can see that it has the leap year calculation.

class DateHelper{

    /*
    * Is valid date and format
    *
    * Format: dd/MM/yyyy
    * valid:
    *   01/12/1996
    * invalid:
    *   01/13/1996
    *
    * Format: MM/dd/yyyy
    * valid:
    *  12/01/1996
    * invalid
    *  13/01/1996
    * */
    static bool isValidDateBirth(String date, String format) {
        try {
            int day, month, year;

            //Get separator data  10/10/2020, 2020-10-10, 10.10.2020
            String separator = RegExp("([-/.])").firstMatch(date).group(0)[0];

            //Split by separator [mm, dd, yyyy]
            var frSplit = format.split(separator);
            //Split by separtor [10, 10, 2020]
            var dtSplit = date.split(separator);

            for (int i = 0; i < frSplit.length; i++) {
                var frm = frSplit[i].toLowerCase();
                var vl = dtSplit[i];

                if (frm == "dd")
                    day = int.parse(vl);
                else if (frm == "mm")
                    month = int.parse(vl);
                else if (frm == "yyyy")
                    year = int.parse(vl);
            }

            //First date check
            //The dart does not throw an exception for invalid date.
            var now = DateTime.now();
            if(month > 12 || month < 1 || day < 1 || day > daysInMonth(month, year) || year < 1810 || (year > now.year && day > now.day && month > now.month))
                throw Exception("Date birth invalid.");

            return true;
        } catch (e) {
            return false;
        }
    }

    static int daysInMonth(int month, int year) {
        int days = 28 + (month + (month/8).floor()) % 2 + 2 % month + 2 * (1/month).floor();
        return (isLeapYear(year) && month == 2)? 29 : days;
    }

    static bool isLeapYear(int year)
        => (( year % 4 == 0 && year % 100 != 0 ) || year % 400 == 0 );
}

Solution 3

Support for validating dates was added for dart in December 2020: https://pub.dev/documentation/intl/latest/intl/DateFormat/parseStrict.html

Share:
6,580
Max
Author by

Max

Updated on December 12, 2022

Comments

  • Max
    Max over 1 year

    If you pass a non-existing/non-real date like: '20181364' (2018/13/64) into DateTime (constructor or parse-method), no exception is thrown. Instead a calculated DateTime is returned.

    Example: '20181364' --> 2019-03-05 00:00:00.000

    How can I check if a given date really exists/is valid?

    I tried to solve this using DartPad (without success), so no Flutter doctor output required here.

    void main() {
      var inputs = ['20180101', // -> 2018-01-01 00:00:00.000
                    '20181231', // -> 2018-12-31 00:00:00.000
                    '20180230', // -> 2018-03-02 00:00:00.000
                    '20181301', // -> 2019-01-01 00:00:00.000
                    '20181364'];// -> 2019-03-05 00:00:00.000
    
      inputs.forEach((input) => print(convertToDate(input)));
    }
    
    String convertToDate(String input){
      return DateTime.parse(input).toString();
    }
    

    It would be great if there exist some kind of method to check if a given date really exists/is valid, e.g.:

    • a validate function in DateTime
    • another lib that does not use DateTime.parse() for validation

    How would you solve this?

  • jdixon04
    jdixon04 almost 5 years
    interesting approach!
  • Max
    Max almost 5 years
    Totally agree, nice and clean approach :) Thank you :)
  • easeccy
    easeccy about 2 years
    This should be the accepted answer.