dart-lang / i18n

A general mono-repo for Dart i18n and l10n packages.
BSD 3-Clause "New" or "Revised" License
58 stars 34 forks source link

DateFormat whitespace problem when parsing times #805

Closed dg76 closed 4 months ago

dg76 commented 4 months ago

Describe the bug DateFormat.jm("en_US").parse("9:01 AM") causes the exception "FormatException: Trying to read   from 9:01 AM at 5" instead of parsing the time. This has worked in intl 0.17.0 but does not work in 0.18.0, 0.18.1 or 0.19.0 any more. Tested with Dart 3.2.3 and 3.3.0.

To Reproduce

import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';

void main(List<String> arguments) async {
  await initializeDateFormatting("en_US");
  print(DateFormat.jm("en_US").parse("9:01 AM"));
}

Output:

Unhandled exception:
FormatException: Trying to read   from 9:01 AM at 5
#0      _DateFormatField.throwFormatException (package:intl/src/intl/date_format_field.dart:87:5)
#1      _DateFormatField.parseLiteral (package:intl/src/intl/date_format_field.dart:56:7)
#2      _DateFormatLiteralField.parse (package:intl/src/intl/date_format_field.dart:100:5)
#3      DateFormat._parse (package:intl/src/intl/date_format.dart:448:13)
#4      DateFormat.parse (package:intl/src/intl/date_format.dart:315:7)
#5      main (file:///.../datetest/bin/datetest.dart:9:32)
<asynchronous suspension>

However, formatting and then parsing a time works fine:

import 'package:intl/date_symbol_data_local.dart';
import 'package:intl/intl.dart';

void main(List<String> arguments) async {
  await initializeDateFormatting("en_US");
  var d = DateFormat.jm("en_US").format(DateTime(2021, 1, 1, 9, 1));
  print(d);
  print(DateFormat.jm("en_US").parse(d));
  print(DateFormat.jm("en_US").parse("9:01 AM"));
}

Output:

9:01 AM
1970-01-01 09:01:00.000
Unhandled exception:
FormatException: Trying to read   from 9:01 AM at 5
#0      _DateFormatField.throwFormatException (package:intl/src/intl/date_format_field.dart:87:5)
#1      _DateFormatField.parseLiteral (package:intl/src/intl/date_format_field.dart:56:7)
#2      _DateFormatLiteralField.parse (package:intl/src/intl/date_format_field.dart:100:5)
#3      DateFormat._parse (package:intl/src/intl/date_format.dart:448:13)
#4      DateFormat.parse (package:intl/src/intl/date_format.dart:315:7)
#5      main (file:///Users/dom/Entwicklung/MacBookPro/git/datetest/bin/datetest.dart:9:32)
<asynchronous suspension>

There seems to be a special whitespace character between "9:01" and "AM" that causes this problem. But I suppose parsing a normal time like "9:01 AM" (e.g. from user input) should work anyway? Thank you for taking a look at this problem! :-)

mosuem commented 4 months ago

This was a recent change to CLDR data, replacing the whitespace before the AM in US English time formatting with a narrow non-breaking space, so the behavior is correct. If you have a non-locale dependent time you would like to parse, try the FixedDateTimeFormatter.

If the use case is for a user to input a time, try to avoid using plain text fields, and use time pickers or similar instead, as parsing plain text fields is very brittle.