Index: tests/lib/i18n/date_time_format_test.dart |
=================================================================== |
--- tests/lib/i18n/date_time_format_test.dart (revision 8510) |
+++ tests/lib/i18n/date_time_format_test.dart (working copy) |
@@ -4,32 +4,290 @@ |
* BSD-style license that can be found in the LICENSE file. |
*/ |
-#library('date_time_format_test'); |
- |
Emily Fortuna
2012/07/31 05:52:53
keep this in.
Alan Knight
2012/08/03 23:02:15
OK. Why do we define libraries for things that don
|
#import('../../../lib/i18n/date_format.dart'); |
#import('../../../lib/unittest/unittest.dart'); |
+#import('../../../lib/i18n/date_time_patterns.dart'); |
+#import('../../../lib/i18n/date_symbol_data.dart'); |
+#import('../../../lib/i18n/intl.dart'); |
+#source('date_time_format_test_data.dart'); |
+ |
/** |
* Tests the DateFormat library in dart. |
*/ |
+var formatsToTest = |
+ const [ |
Emily Fortuna
2012/07/31 05:52:53
move this up to the previous line
Alan Knight
2012/08/03 23:02:15
Done.
|
+ DateFormat.DAY, |
+ DateFormat.ABBR_WEEKDAY, |
+ DateFormat.WEEKDAY, |
+ DateFormat.ABBR_STANDALONE_MONTH, |
+ DateFormat.STANDALONE_MONTH, |
+ DateFormat.NUM_MONTH, |
+ DateFormat.NUM_MONTH_DAY, |
+ DateFormat.NUM_MONTH_WEEKDAY_DAY, |
+ DateFormat.ABBR_MONTH, |
+ DateFormat.ABBR_MONTH_DAY, |
+ DateFormat.ABBR_MONTH_WEEKDAY_DAY, |
+ DateFormat.MONTH, |
+ DateFormat.MONTH_DAY, |
+ DateFormat.MONTH_WEEKDAY_DAY, |
+ DateFormat.ABBR_QUARTER, |
+ DateFormat.QUARTER, |
+ DateFormat.YEAR, |
+ DateFormat.YEAR_NUM_MONTH, |
+ DateFormat.YEAR_NUM_MONTH_DAY, |
+ DateFormat.YEAR_NUM_MONTH_WEEKDAY_DAY, |
+ DateFormat.YEAR_ABBR_MONTH, |
+ DateFormat.YEAR_ABBR_MONTH_DAY, |
+ DateFormat.YEAR_ABBR_MONTH_WEEKDAY_DAY, |
+ DateFormat.YEAR_MONTH, |
+ DateFormat.YEAR_MONTH_DAY, |
+ DateFormat.YEAR_MONTH_WEEKDAY_DAY, |
+//TODO(alanknight): CLDR and ICU appear to disagree on these for Japanese |
Emily Fortuna
2012/07/31 05:52:53
indentation
Alan Knight
2012/08/03 23:02:15
Done.
|
+// DateFormat.YEAR_ABBR_QUARTER, |
+// DateFormat.YEAR_QUARTER, |
+ DateFormat.HOUR24, |
+ DateFormat.HOUR24_MINUTE, |
+ DateFormat.HOUR24_MINUTE_SECOND, |
+ DateFormat.HOUR, |
+ DateFormat.HOUR_MINUTE, |
+ DateFormat.HOUR_MINUTE_SECOND, |
+// TODO(alanknight): Time zone support |
+// DateFormat.HOUR_MINUTE_GENERIC_TZ, |
+// DateFormat.HOUR_MINUTE_TZ, |
+// DateFormat.HOUR_GENERIC_TZ, |
+// DateFormat.HOUR_TZ, |
+ DateFormat.MINUTE, |
+ DateFormat.MINUTE_SECOND, |
+ DateFormat.SECOND |
+// ABBR_GENERIC_TZ, |
+// GENERIC_TZ, |
+// ABBR_SPECIFIC_TZ, |
+// SPECIFIC_TZ, |
+// ABBR_UTC_TZ |
+ ]; |
+ |
+var icuFormatNamesToTest = |
+// It would be really nice to not have to duplicate this and just be able |
+// to use the names to get reflective access. |
+ const [ |
+ "DAY", |
+ "ABBR_WEEKDAY", |
+ "WEEKDAY", |
+ "ABBR_STANDALONE_MONTH", |
+ "STANDALONE_MONTH", |
+ "NUM_MONTH", |
+ "NUM_MONTH_DAY", |
+ "NUM_MONTH_WEEKDAY_DAY", |
+ "ABBR_MONTH", |
+ "ABBR_MONTH_DAY", |
+ "ABBR_MONTH_WEEKDAY_DAY", |
+ "MONTH", |
+ "MONTH_DAY", |
+ "MONTH_WEEKDAY_DAY", |
+ "ABBR_QUARTER", |
+ "QUARTER", |
+ "YEAR", |
+ "YEAR_NUM_MONTH", |
+ "YEAR_NUM_MONTH_DAY", |
+ "YEAR_NUM_MONTH_WEEKDAY_DAY", |
+ "YEAR_ABBR_MONTH", |
+ "YEAR_ABBR_MONTH_DAY", |
+ "YEAR_ABBR_MONTH_WEEKDAY_DAY", |
+ "YEAR_MONTH", |
+ "YEAR_MONTH_DAY", |
+ "YEAR_MONTH_WEEKDAY_DAY", |
+//TODO(alanknight): CLDR and ICU appear to disagree on these for Japanese. |
+// omit for the time being |
+// "YEAR_ABBR_QUARTER", |
+// "YEAR_QUARTER", |
+ "HOUR24", |
+ "HOUR24_MINUTE", |
+ "HOUR24_MINUTE_SECOND", |
+ "HOUR", |
+ "HOUR_MINUTE", |
+ "HOUR_MINUTE_SECOND", |
+// TODO(alanknight): Time zone support |
+// "HOUR_MINUTE_GENERIC_TZ", |
+// "HOUR_MINUTE_TZ", |
+// "HOUR_GENERIC_TZ", |
+// "HOUR_TZ", |
+ "MINUTE", |
+ "MINUTE_SECOND", |
+ "SECOND" |
+// ABBR_GENERIC_TZ, |
+// GENERIC_TZ, |
+// ABBR_SPECIFIC_TZ, |
+// SPECIFIC_TZ, |
+// ABBR_UTC_TZ |
+ ]; |
+ |
+ |
main() { |
- test('Date formatting', () { |
- var date_format = new DateFormat.fullDate(); |
- Date date = new Date.now(); |
- // TODO(efortuna): Change the expectation once we have a functioning date |
- // formatting class. |
- Expect.stringEquals(date.toString(), date_format.format(date)); |
- |
- date_format = new DateFormat("hh:mm:ss"); |
- Expect.stringEquals(date.toString(), date_format.format(date)); |
+ |
Emily Fortuna
2012/07/31 05:52:53
extra whitespace
Alan Knight
2012/08/03 23:02:15
Done.
|
+ test('Basic date format parsing', () { |
+ var date_format = new DateFormat(); |
Emily Fortuna
2012/07/31 05:52:53
indentation. please!
Alan Knight
2012/08/03 23:02:15
Done.
|
+ // With the apparent removal of recursivelyMatches these don't work. |
+ expect( |
+ (date_format.parsePattern("hh:mm:ss")).map((x)=>x.string), |
Emily Fortuna
2012/07/31 05:52:53
extra paren here starting
Alan Knight
2012/08/03 23:02:15
Done.
|
+ orderedEquals(["hh",":", "mm",":","ss"])); |
+ expect( |
+ (date_format.parsePattern("hh:mm:ss")).map((x)=>x.string), |
+ orderedEquals(["hh",":", "mm",":","ss"])); |
+ var types = ['FIELD', 'LITERAL', 'FIELD' ,'LITERAL' ,'FIELD']; |
+ expect(date_format.parsePattern("hh:mm:ss").map((x)=>x.type), |
+ orderedEquals(types)); |
Emily Fortuna
2012/07/31 05:52:53
test some other cases for parsing?
Alan Knight
2012/08/03 23:02:15
Possible, although this functionality is also well
|
}); |
- test('Date parsing', () { |
- var date_format = new DateFormat.fullDate(); |
- Date date = new Date.now(); |
- // TODO(efortuna): Change the expectation once we have a functioning date |
- // formatting class. |
- Expect.stringEquals(date_format.parse(date.toString()), date.toString()); |
+ test('Test ALL the supported formats on representative locales', () { |
+ var aDate = new Date(2012,1,27,20,58,59,0,false); |
+ testLocale("en_US", English, aDate); |
+ testLocale("de_DE", German, aDate); |
+ testLocale("fr_FR", French, aDate); |
+ testLocale("ja_JP", Japanese, aDate); |
+ testLocale("el_GR", Greek, aDate); |
+ testLocale("de_AT", Austrian, aDate); |
}); |
+ |
+ test('Test round-trip parsing of dates', () { |
+ var hours = [0, 1, 11, 12, 13, 23]; |
+ var months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; |
+ var locales = dateTimePatterns.getKeys(); |
+ for (var locale in locales) { |
+ for (var month in months) { |
+ var aDate = new Date(2012,month,27,13,58,59,012,false); |
+ testRoundTripParsing(locale, aDate); |
+ } |
+ for (var hour in hours) { |
+ var aDate = new Date(2012,1,27,hour,58,59,123,false); |
+ testRoundTripParsing(locale, aDate); |
+ } |
+ } |
+ }); |
+ |
+ test('Patterns and symbols have the same coverage',() { |
+ var patterns = ["en_ISO"]; |
+ patterns.addAll(dateTimePatterns.getKeys()); |
+ var compare = (a,b) => a.compareTo(b); |
+ patterns.sort(compare); |
+ var symbols = dateTimeSymbols.getKeys() as List; |
+ symbols.sort(compare); |
+ expect(patterns.length, equals(symbols.length)); |
+ for (var i = 0; i < patterns.length; i++) |
+ expect(patterns[i], equals(symbols[i])); |
+ }); |
+ |
+ test('Test malformed locales', () { |
+ var aDate = new Date(2012,1,27,20,58,59,0,false); |
+ // Austrian is a useful test locale here because it differs slightly |
+ // from the generic "de" locale so we can tell the difference between |
+ // correcting to "de_AT" and falling back to just "de". |
+ testLocale('de-AT', Austrian, aDate); |
+ testLocale('de_at', Austrian,aDate); |
+ testLocale('de-at', Austrian,aDate); |
+ // testLocale('fr-fr', French, aDate); |
+ }); |
+ |
+ test('Test format creation via Intl', () { |
+ var staticDefaultLocale = Intl.Date('jms'); |
+ var staticWithLocale = Intl.Date('jms','ja_JP'); |
+ var intl = new Intl('ja_JP'); |
+ var instanceJP = intl.date('jms'); |
+ var instanceUS = intl.date('jms', 'en_US'); |
+ var blank = intl.date(); |
+ blank.pattern = 'jms'; |
+ var date = new Date(2012,1,27,20,58,59,0,false); |
+ expect(staticDefaultLocale.format(date),equals("8:58:59 PM")); |
+ expect(staticWithLocale.format(date),equals("20:58:59")); |
+ expect(instanceJP.format(date),equals("20:58:59")); |
+ expect(instanceUS.format(date),equals("8:58:59 PM")); |
+ expect(blank.format(date), equals("20:58:59")); |
+ }); |
+ |
+ test('Test explicit format string', () { |
+ var aDate = new Date(2012,1,27,20,58,59,0,false); |
+ // An explicit format that doesn't conform to any skeleton |
+ var us = new DateFormat('yy //// :D \\\\ dd:ss ^&@ M'); |
+ expect(us.format(aDate), equals("12 //// :D \\\\ 27:59 ^&@ 1")); |
+ // The result won't change with locale unless we use fields that are words. |
+ var greek = new DateFormat('yy //// :D \\\\ dd:ss ^&@ M', 'el_GR'); |
+ expect(greek.format(aDate), equals("12 //// :D \\\\ 27:59 ^&@ 1")); |
+ var usWithWords = new DateFormat('yy / :D \ dd:ss ^&@ MMM', 'en_US'); |
+ var greekWithWords = new DateFormat('yy / :D \ dd:ss ^&@ MMM', 'el_GR'); |
+ expect( |
+ usWithWords.format(aDate), |
+ equals("12 / :D \ 27:59 ^&@ Jan")); |
+ expect( |
+ greekWithWords.format(aDate), |
+ equals("12 / :D \ 27:59 ^&@ Ιαν")); |
+ var escaped = new DateFormat("hh 'o''clock'"); |
+ expect(escaped.format(aDate),equals("08 o'clock")); |
+ var reParsed = escaped.parse(escaped.format(aDate)); |
+ expect(escaped.format(reParsed), equals(escaped.format(aDate))); |
+ }); |
+ |
+ test('Test fractional seconds padding', () { |
+ var one = new Date(2012,1,27,20,58,59,1,false); |
+ var oneHundred = new Date(2012,1,27,20,58,59,100,false); |
+ var fractional = new DateFormat('hh:mm:ss.SSS', 'en_US'); |
+ expect(fractional.format(one),equals('08:58:59.001')); |
+ expect(fractional.format(oneHundred),equals('08:58:59.100')); |
+ var long = new DateFormat('ss.SSSSSSSS', 'en_US'); |
+ expect(long.format(oneHundred),equals('59.10000000')); |
+ expect(long.format(one),equals('59.00100000')); |
+ }); |
} |
+ |
+/** |
+ * Exercise all of the formats we have explicitly defined on a particular |
+ * locale. Expects to be given a Map from ICU constant names to the |
Emily Fortuna
2012/07/31 05:52:53
info about the parameters? nit: Can this function
Alan Knight
2012/08/03 23:02:15
Done.
|
+ * expected result. |
+ */ |
+testLocale(String localeName, Map expectedResults, Date date) { |
+ var intl = new Intl(localeName); |
+ for(int i=0; i<formatsToTest.length;i++) { |
Emily Fortuna
2012/07/31 05:52:53
spacing. i < formatsToTest.length; i++ here and ot
Alan Knight
2012/08/03 23:02:15
Done.
|
+ var skeleton = formatsToTest[i]; |
+ var format = intl.date(skeleton); |
+ var icuName = icuFormatNamesToTest[i]; |
+//Some useful statements to uncomment if you have to debug incorrect results. |
+// print("Expect: ${expectedResults[formatName]} from format $formatName " |
Emily Fortuna
2012/07/31 05:52:53
cut commented out code :-/
Alan Knight
2012/08/03 23:02:15
Done.
|
+// "($formatString) which resolves to "); |
+// print("${dateTimePatterns[format.locale][formatString]}"); |
+// print("Actual Result: ${format.format(date)}"); |
+ var actualResult = format.format(date); |
+ expect(expectedResults[icuName],equals(actualResult)); |
Emily Fortuna
2012/07/31 05:52:53
spacing after ,
Alan Knight
2012/08/03 23:02:15
Done.
|
+ } |
+} |
+ |
+testRoundTripParsing(String localeName, Date date) { |
+ // In order to test parsing, we can't just read back the date, because |
+ // printing in most formats loses information. But we can test that |
+ // what we parsed back prints the same as what we originally printed. |
+ // At least in most cases. In some cases, we can't even do that. e.g. |
+ // the skeleton WEEKDAY can't be reconstructed at all, and YEAR_MONTH |
+ // formats don't give us enough information to construct a valid date. |
+ var badSkeletons = [ |
+ DateFormat.ABBR_WEEKDAY, |
+ DateFormat.WEEKDAY, |
+ DateFormat.QUARTER, |
+ DateFormat.ABBR_QUARTER, |
+ DateFormat.YEAR, |
+ DateFormat.YEAR_NUM_MONTH, |
+ DateFormat.YEAR_ABBR_MONTH, |
+ DateFormat.YEAR_MONTH]; |
+ for(int i=0; i<formatsToTest.length;i++) { |
+ var skeleton = formatsToTest[i]; |
+ var format = new DateFormat(skeleton,localeName); |
Emily Fortuna
2012/07/31 05:52:53
space after ,
Alan Knight
2012/08/03 23:02:15
Done.
|
+ var badPatterns = badSkeletons.map( |
+ (x) => new DateFormat(x,format.locale).pattern); |
+ if (!badPatterns.some((x) => x == format.pattern)) { |
Emily Fortuna
2012/07/31 05:52:53
?
Alan Knight
2012/08/03 23:02:15
If this format's pattern is not in the list of pat
|
+ var actualResult = format.format(date); |
+ var parsed = format.parse(actualResult); |
+ var thenPrintAgain = format.format(parsed); |
+ expect(thenPrintAgain,equals(actualResult)); |
Emily Fortuna
2012/07/31 05:52:53
space after , .
Alan Knight
2012/08/03 23:02:15
Done.
|
+ } |
+ } |
+} |
+ |
+ |