| OLD | NEW |
| 1 /** | 1 /** |
| 2 * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 * Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 3 * for details. All rights reserved. Use of this source code is governed by a | 3 * for details. All rights reserved. Use of this source code is governed by a |
| 4 * BSD-style license that can be found in the LICENSE file. | 4 * BSD-style license that can be found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #library('date_time_format_test'); | 7 #library('date_time_format_test'); |
| 8 | 8 |
| 9 #import('../../../lib/i18n/intl.dart'); | 9 #import('../../../lib/i18n/intl.dart'); |
| 10 #import('../../../lib/i18n/date_format.dart'); | |
| 11 #import('../../../lib/unittest/unittest.dart'); | 10 #import('../../../lib/unittest/unittest.dart'); |
| 12 #import('../../../lib/i18n/date_time_patterns.dart'); | |
| 13 #import('../../../lib/i18n/date_symbol_data.dart'); | |
| 14 #import('../../../lib/i18n/intl.dart'); | |
| 15 | |
| 16 #source('date_time_format_test_data.dart'); | |
| 17 | 11 |
| 18 /** | 12 /** |
| 19 * Tests the DateFormat library in dart. | 13 * Tests the DateFormat library in dart. |
| 20 */ | 14 */ |
| 21 | 15 |
| 22 var formatsToTest = const [ | |
| 23 DateFormat.DAY, | |
| 24 DateFormat.ABBR_WEEKDAY, | |
| 25 DateFormat.WEEKDAY, | |
| 26 DateFormat.ABBR_STANDALONE_MONTH, | |
| 27 DateFormat.STANDALONE_MONTH, | |
| 28 DateFormat.NUM_MONTH, | |
| 29 DateFormat.NUM_MONTH_DAY, | |
| 30 DateFormat.NUM_MONTH_WEEKDAY_DAY, | |
| 31 DateFormat.ABBR_MONTH, | |
| 32 DateFormat.ABBR_MONTH_DAY, | |
| 33 DateFormat.ABBR_MONTH_WEEKDAY_DAY, | |
| 34 DateFormat.MONTH, | |
| 35 DateFormat.MONTH_DAY, | |
| 36 DateFormat.MONTH_WEEKDAY_DAY, | |
| 37 DateFormat.ABBR_QUARTER, | |
| 38 DateFormat.QUARTER, | |
| 39 DateFormat.YEAR, | |
| 40 DateFormat.YEAR_NUM_MONTH, | |
| 41 DateFormat.YEAR_NUM_MONTH_DAY, | |
| 42 DateFormat.YEAR_NUM_MONTH_WEEKDAY_DAY, | |
| 43 DateFormat.YEAR_ABBR_MONTH, | |
| 44 DateFormat.YEAR_ABBR_MONTH_DAY, | |
| 45 DateFormat.YEAR_ABBR_MONTH_WEEKDAY_DAY, | |
| 46 DateFormat.YEAR_MONTH, | |
| 47 DateFormat.YEAR_MONTH_DAY, | |
| 48 DateFormat.YEAR_MONTH_WEEKDAY_DAY, | |
| 49 // TODO(alanknight): CLDR and ICU appear to disagree on these for Japanese | |
| 50 // DateFormat.YEAR_ABBR_QUARTER, | |
| 51 // DateFormat.YEAR_QUARTER, | |
| 52 DateFormat.HOUR24, | |
| 53 DateFormat.HOUR24_MINUTE, | |
| 54 DateFormat.HOUR24_MINUTE_SECOND, | |
| 55 DateFormat.HOUR, | |
| 56 DateFormat.HOUR_MINUTE, | |
| 57 DateFormat.HOUR_MINUTE_SECOND, | |
| 58 // TODO(alanknight): Time zone support | |
| 59 // DateFormat.HOUR_MINUTE_GENERIC_TZ, | |
| 60 // DateFormat.HOUR_MINUTE_TZ, | |
| 61 // DateFormat.HOUR_GENERIC_TZ, | |
| 62 // DateFormat.HOUR_TZ, | |
| 63 DateFormat.MINUTE, | |
| 64 DateFormat.MINUTE_SECOND, | |
| 65 DateFormat.SECOND | |
| 66 // ABBR_GENERIC_TZ, | |
| 67 // GENERIC_TZ, | |
| 68 // ABBR_SPECIFIC_TZ, | |
| 69 // SPECIFIC_TZ, | |
| 70 // ABBR_UTC_TZ | |
| 71 ]; | |
| 72 | |
| 73 var icuFormatNamesToTest = const [ | |
| 74 // It would be really nice to not have to duplicate this and just be able | |
| 75 // to use the names to get reflective access. | |
| 76 "DAY", | |
| 77 "ABBR_WEEKDAY", | |
| 78 "WEEKDAY", | |
| 79 "ABBR_STANDALONE_MONTH", | |
| 80 "STANDALONE_MONTH", | |
| 81 "NUM_MONTH", | |
| 82 "NUM_MONTH_DAY", | |
| 83 "NUM_MONTH_WEEKDAY_DAY", | |
| 84 "ABBR_MONTH", | |
| 85 "ABBR_MONTH_DAY", | |
| 86 "ABBR_MONTH_WEEKDAY_DAY", | |
| 87 "MONTH", | |
| 88 "MONTH_DAY", | |
| 89 "MONTH_WEEKDAY_DAY", | |
| 90 "ABBR_QUARTER", | |
| 91 "QUARTER", | |
| 92 "YEAR", | |
| 93 "YEAR_NUM_MONTH", | |
| 94 "YEAR_NUM_MONTH_DAY", | |
| 95 "YEAR_NUM_MONTH_WEEKDAY_DAY", | |
| 96 "YEAR_ABBR_MONTH", | |
| 97 "YEAR_ABBR_MONTH_DAY", | |
| 98 "YEAR_ABBR_MONTH_WEEKDAY_DAY", | |
| 99 "YEAR_MONTH", | |
| 100 "YEAR_MONTH_DAY", | |
| 101 "YEAR_MONTH_WEEKDAY_DAY", | |
| 102 // TODO(alanknight): CLDR and ICU appear to disagree on these for Japanese. | |
| 103 // omit for the time being | |
| 104 // "YEAR_ABBR_QUARTER", | |
| 105 // "YEAR_QUARTER", | |
| 106 "HOUR24", | |
| 107 "HOUR24_MINUTE", | |
| 108 "HOUR24_MINUTE_SECOND", | |
| 109 "HOUR", | |
| 110 "HOUR_MINUTE", | |
| 111 "HOUR_MINUTE_SECOND", | |
| 112 // TODO(alanknight): Time zone support | |
| 113 // "HOUR_MINUTE_GENERIC_TZ", | |
| 114 // "HOUR_MINUTE_TZ", | |
| 115 // "HOUR_GENERIC_TZ", | |
| 116 // "HOUR_TZ", | |
| 117 "MINUTE", | |
| 118 "MINUTE_SECOND", | |
| 119 "SECOND" | |
| 120 // ABBR_GENERIC_TZ, | |
| 121 // GENERIC_TZ, | |
| 122 // ABBR_SPECIFIC_TZ, | |
| 123 // SPECIFIC_TZ, | |
| 124 // ABBR_UTC_TZ | |
| 125 ]; | |
| 126 | |
| 127 /** | |
| 128 * Exercise all of the formats we have explicitly defined on a particular | |
| 129 * locale. [expectedResults] is a map from ICU format names to the | |
| 130 * expected result of formatting [date] according to that format in | |
| 131 * [locale]. | |
| 132 */ | |
| 133 testLocale(String localeName, Map expectedResults, Date date) { | |
| 134 var intl = new Intl(localeName); | |
| 135 for(int i=0; i<formatsToTest.length; i++) { | |
| 136 var skeleton = formatsToTest[i]; | |
| 137 var format = intl.date(skeleton); | |
| 138 var icuName = icuFormatNamesToTest[i]; | |
| 139 var actualResult = format.format(date); | |
| 140 expect(expectedResults[icuName], equals(actualResult)); | |
| 141 } | |
| 142 } | |
| 143 | |
| 144 testRoundTripParsing(String localeName, Date date) { | |
| 145 // In order to test parsing, we can't just read back the date, because | |
| 146 // printing in most formats loses information. But we can test that | |
| 147 // what we parsed back prints the same as what we originally printed. | |
| 148 // At least in most cases. In some cases, we can't even do that. e.g. | |
| 149 // the skeleton WEEKDAY can't be reconstructed at all, and YEAR_MONTH | |
| 150 // formats don't give us enough information to construct a valid date. | |
| 151 var badSkeletons = [ | |
| 152 DateFormat.ABBR_WEEKDAY, | |
| 153 DateFormat.WEEKDAY, | |
| 154 DateFormat.QUARTER, | |
| 155 DateFormat.ABBR_QUARTER, | |
| 156 DateFormat.YEAR, | |
| 157 DateFormat.YEAR_NUM_MONTH, | |
| 158 DateFormat.YEAR_ABBR_MONTH, | |
| 159 DateFormat.YEAR_MONTH]; | |
| 160 for(int i = 0; i < formatsToTest.length; i++) { | |
| 161 var skeleton = formatsToTest[i]; | |
| 162 var format = new DateFormat(skeleton, localeName); | |
| 163 var badPatterns = badSkeletons.map( | |
| 164 (x) => new DateFormat(x, format.locale).pattern); | |
| 165 | |
| 166 if (!badPatterns.some((x) => x == format.pattern)) { | |
| 167 var actualResult = format.format(date); | |
| 168 var parsed = format.parse(actualResult); | |
| 169 var thenPrintAgain = format.format(parsed); | |
| 170 expect(thenPrintAgain, equals(actualResult)); | |
| 171 } | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 main() { | 16 main() { |
| 176 test('Basic date format parsing', () { | 17 test('Date formatting', () { |
| 177 var date_format = new DateFormat(); | 18 var date_format = new DateFormat.fullDate(); |
| 178 expect( | 19 Date date = new Date.now(); |
| 179 date_format.parsePattern("hh:mm:ss").map((x) => x.pattern), | 20 // TODO(efortuna): Change the expectation once we have a functioning date |
| 180 orderedEquals(["hh",":", "mm",":","ss"])); | 21 // formatting class. |
| 181 expect( | 22 Expect.stringEquals(date.toString(), date_format.format(date)); |
| 182 date_format.parsePattern("hh:mm:ss").map((x) => x.pattern), | 23 |
| 183 orderedEquals(["hh",":", "mm",":","ss"])); | 24 date_format = new DateFormat("hh:mm:ss"); |
| 25 Expect.stringEquals(date.toString(), date_format.format(date)); |
| 184 }); | 26 }); |
| 185 | 27 |
| 186 test('Test ALL the supported formats on representative locales', () { | 28 test('Date parsing', () { |
| 187 var aDate = new Date(2012, 1, 27, 20, 58, 59, 0, false); | 29 var date_format = new DateFormat.fullDate(); |
| 188 testLocale("en_US", English, aDate); | 30 Date date = new Date.now(); |
| 189 testLocale("de_DE", German, aDate); | 31 // TODO(efortuna): Change the expectation once we have a functioning date |
| 190 testLocale("fr_FR", French, aDate); | 32 // formatting class. |
| 191 testLocale("ja_JP", Japanese, aDate); | 33 Expect.stringEquals(date_format.parse(date.toString()), date.toString()); |
| 192 testLocale("el_GR", Greek, aDate); | |
| 193 testLocale("de_AT", Austrian, aDate); | |
| 194 }); | 34 }); |
| 195 | 35 } |
| 196 test('Test round-trip parsing of dates', () { | |
| 197 var hours = [0, 1, 11, 12, 13, 23]; | |
| 198 var months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; | |
| 199 var locales = dateTimePatterns.getKeys(); | |
| 200 for (var locale in locales) { | |
| 201 for (var month in months) { | |
| 202 var aDate = new Date(2012, month, 27, 13, 58, 59, 012, false); | |
| 203 testRoundTripParsing(locale, aDate); | |
| 204 } | |
| 205 for (var hour in hours) { | |
| 206 var aDate = new Date(2012, 1, 27, hour, 58, 59, 123, false); | |
| 207 testRoundTripParsing(locale, aDate); | |
| 208 } | |
| 209 } | |
| 210 }); | |
| 211 | |
| 212 test('Patterns and symbols have the same coverage',() { | |
| 213 var patterns = ["en_ISO"]; | |
| 214 patterns.addAll(dateTimePatterns.getKeys()); | |
| 215 var compare = (a, b) => a.compareTo(b); | |
| 216 patterns.sort(compare); | |
| 217 var symbols = dateTimeSymbols.getKeys() as List; | |
| 218 symbols.sort(compare); | |
| 219 expect(patterns.length, equals(symbols.length)); | |
| 220 for (var i = 0; i < patterns.length; i++) | |
| 221 expect(patterns[i], equals(symbols[i])); | |
| 222 }); | |
| 223 | |
| 224 test('Test malformed locales', () { | |
| 225 var aDate = new Date(2012, 1, 27, 20, 58, 59, 0, false); | |
| 226 // Austrian is a useful test locale here because it differs slightly | |
| 227 // from the generic "de" locale so we can tell the difference between | |
| 228 // correcting to "de_AT" and falling back to just "de". | |
| 229 testLocale('de-AT', Austrian, aDate); | |
| 230 testLocale('de_at', Austrian, aDate); | |
| 231 testLocale('de-at', Austrian, aDate); | |
| 232 }); | |
| 233 | |
| 234 test('Test format creation via Intl', () { | |
| 235 var intl = new Intl('ja_JP'); | |
| 236 var instanceJP = intl.date('jms'); | |
| 237 var instanceUS = intl.date('jms', 'en_US'); | |
| 238 var blank = intl.date('jms'); | |
| 239 var date = new Date(2012, 1, 27, 20, 58, 59, 0, false); | |
| 240 expect(instanceJP.format(date), equals("20:58:59")); | |
| 241 expect(instanceUS.format(date), equals("8:58:59 PM")); | |
| 242 expect(blank.format(date), equals("20:58:59")); | |
| 243 }); | |
| 244 | |
| 245 test('Test explicit format string', () { | |
| 246 var aDate = new Date(2012, 1, 27, 20, 58, 59, 0, false); | |
| 247 // An explicit format that doesn't conform to any skeleton | |
| 248 var us = new DateFormat(@'yy //// :D \\\\ dd:ss ^&@ M'); | |
| 249 expect(us.format(aDate), equals(@"12 //// :D \\\\ 27:59 ^&@ 1")); | |
| 250 // The result won't change with locale unless we use fields that are words. | |
| 251 var greek = new DateFormat(@'yy //// :D \\\\ dd:ss ^&@ M', 'el_GR'); | |
| 252 expect(greek.format(aDate), equals(@"12 //// :D \\\\ 27:59 ^&@ 1")); | |
| 253 var usWithWords = new DateFormat('yy / :D \\ dd:ss ^&@ MMM', 'en_US'); | |
| 254 var greekWithWords = new DateFormat('yy / :D \\ dd:ss ^&@ MMM', 'el_GR'); | |
| 255 expect( | |
| 256 usWithWords.format(aDate), | |
| 257 equals(@"12 / :D \ 27:59 ^&@ Jan")); | |
| 258 expect( | |
| 259 greekWithWords.format(aDate), | |
| 260 equals(@"12 / :D \ 27:59 ^&@ Ιαν")); | |
| 261 var escaped = new DateFormat(@"hh 'o''clock'"); | |
| 262 expect(escaped.format(aDate), equals(@"08 o'clock")); | |
| 263 var reParsed = escaped.parse(escaped.format(aDate)); | |
| 264 expect(escaped.format(reParsed), equals(escaped.format(aDate))); | |
| 265 var noSeparators = new DateFormat('HHmmss'); | |
| 266 expect(noSeparators.format(aDate), equals("205859")); | |
| 267 }); | |
| 268 | |
| 269 test('Test fractional seconds padding', () { | |
| 270 var one = new Date(2012, 1, 27, 20, 58, 59, 1, false); | |
| 271 var oneHundred = new Date(2012, 1, 27, 20, 58, 59, 100, false); | |
| 272 var fractional = new DateFormat('hh:mm:ss.SSS', 'en_US'); | |
| 273 expect(fractional.format(one), equals('08:58:59.001')); | |
| 274 expect(fractional.format(oneHundred), equals('08:58:59.100')); | |
| 275 var long = new DateFormat('ss.SSSSSSSS', 'en_US'); | |
| 276 expect(long.format(oneHundred), equals('59.10000000')); | |
| 277 expect(long.format(one), equals('59.00100000')); | |
| 278 }); | |
| 279 | |
| 280 test('Test parseUTC', () { | |
| 281 var local = new Date(2012, 1, 27, 20, 58, 59, 1, false); | |
| 282 var utc = new Date(2012, 1, 27, 20, 58, 59, 1, true); | |
| 283 var offset = utc.difference(local); | |
| 284 var format = new DateFormat('yyyy-MM-dd HH:mm:ss'); | |
| 285 var localPrinted = format.format(local); | |
| 286 var parsed = format.parse(localPrinted); | |
| 287 var parsedUTC = format.parseUTC(format.format(utc)); | |
| 288 var parsedOffset = parsedUTC.difference(parsed); | |
| 289 expect(parsedOffset, equals(offset)); | |
| 290 expect(utc.hour, equals(parsedUTC.hour)); | |
| 291 expect(local.hour, equals(parsed.hour)); | |
| 292 }); | |
| 293 } | |
| OLD | NEW |