1

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?

KY1VSTAR
  • 395
  • 4
  • 16
  • This is definitely strange.. Try filing an issue here (or see if there's one already): https://github.com/dart-lang/intl/issues – osaxma Feb 09 '22 at 11:22
  • 2
    There is an issue already – it is https://github.com/dart-lang/intl/issues/210 / Seems like both methods are not really designed to work fully reversible. – Tim Brückner Feb 09 '22 at 11:43
  • 2
    See https://stackoverflow.com/a/61394854/ – jamesdlin Feb 09 '22 at 19:46

1 Answers1

2

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;
    }
  }
}
Tim Brückner
  • 1,928
  • 2
  • 16
  • 27
  • Thanks for answer. Given that I cannot change format of string coming from somewhere else what would you recommend to parse it without separators? – KY1VSTAR Feb 09 '22 at 11:47
  • If the format never changes, I would write a small fixed length parser for the date. You could implement that as an extension to String or DateTime for example. It doesn't matter much. – Tim Brückner Feb 09 '22 at 11:52
  • 1
    I added a small workaround, which might help you with this issue. Just be aware, that DateFormat is locale aware. You should probably use a fixed locale with it in this case. – Tim Brückner Feb 09 '22 at 12:18