flutterdartdate-formatflutter-intldart-intl

Dart DateFormat inconsistency


I'm trying to parse date string that looks like this Feb0920221500 (month, day in month, year, hours, minutes). But when I use MMMddyyyyHmm pattern I always get a FormatException. Furthermore intl's DateFormat fails to parse back a date which it has formatted before:

import 'package:intl/intl.dart';

void main() {
  final dateFormat = DateFormat("MMMddyyyyHmm");
  final dateString = dateFormat.format(DateTime.now());
  print(dateString);
  final date = dateFormat.parse(dateString);
  print(date);
}

Output:

Feb0920221511
Uncaught Error: FormatException: Trying to read yyyy from Feb0920221511 at position 13

What am I doing wrong?


Solution

  • You are running into this issue: https://github.com/dart-lang/intl/issues/210

    TL/DR: Both methods are not designed to work fully reversible, if I understood the package maintainers correctly.

    Try to introduce field separators like a space or a dot as a workaround:

      final dateFormat = DateFormat("MMM dd yyyy H mm");
      final dateString = dateFormat.format(DateTime.now());
      print(dateString);
      print(dateFormat.parseStdaterict(dateString));
    

    If the format of the given date String cannot be changed, you still have the possibility to make it work with a hack like this. Just make sure to handle errors gracefully.

    import 'package:intl/intl.dart';
    
    Future<void> main() async {
      final parsedDate = 'Feb0920221511'.parseToDate();
      print(parsedDate.toIso8601String());
    }
    
    extension CustomDateParser on String {
      DateTime parseToDate() {
        try {
          final month = substring(0, 3);
          final day = substring(3, 5);
          final year = substring(5, 9);
          final hour = substring(9, 11);
          final minute = substring(11, 13);
    
          final paddedDateString = '$month $day $year $hour $minute';
          final dateFormat = DateFormat('MMM dd yyyy H mm');
          return dateFormat.parse(paddedDateString);
        } catch (e) {
          // handle error
          print(e);
          rethrow;
        }
      }
    }