DateTimeFormat.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. describe("errors", () => {
  2. test("structurally invalid tag", () => {
  3. expect(() => {
  4. new Intl.DateTimeFormat("root");
  5. }).toThrowWithMessage(RangeError, "root is not a structurally valid language tag");
  6. expect(() => {
  7. new Intl.DateTimeFormat("en-");
  8. }).toThrowWithMessage(RangeError, "en- is not a structurally valid language tag");
  9. expect(() => {
  10. new Intl.DateTimeFormat("Latn");
  11. }).toThrowWithMessage(RangeError, "Latn is not a structurally valid language tag");
  12. expect(() => {
  13. new Intl.DateTimeFormat("en-u-aa-U-aa");
  14. }).toThrowWithMessage(RangeError, "en-u-aa-U-aa is not a structurally valid language tag");
  15. });
  16. test("options is an invalid type", () => {
  17. expect(() => {
  18. new Intl.DateTimeFormat("en", null);
  19. }).toThrowWithMessage(TypeError, "ToObject on null or undefined");
  20. });
  21. test("localeMatcher option is invalid", () => {
  22. expect(() => {
  23. new Intl.DateTimeFormat("en", { localeMatcher: "hello!" });
  24. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option localeMatcher");
  25. });
  26. test("calendar option is invalid", () => {
  27. expect(() => {
  28. new Intl.DateTimeFormat("en", { calendar: "hello!" });
  29. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option calendar");
  30. });
  31. test("numberingSystem option is invalid", () => {
  32. expect(() => {
  33. new Intl.DateTimeFormat("en", { numberingSystem: "hello!" });
  34. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option numberingSystem");
  35. });
  36. test("hourCycle option is invalid", () => {
  37. expect(() => {
  38. new Intl.DateTimeFormat("en", { hourCycle: "hello!" });
  39. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option hourCycle");
  40. });
  41. test("timeZone option is invalid", () => {
  42. ["hello!", "+1", "+1:02", "+01:02:03"].forEach(timeZone => {
  43. expect(() => {
  44. new Intl.DateTimeFormat("en", { timeZone: timeZone });
  45. }).toThrowWithMessage(
  46. RangeError,
  47. `${timeZone} is not a valid value for option timeZone`
  48. );
  49. });
  50. });
  51. test("era option is invalid", () => {
  52. expect(() => {
  53. new Intl.DateTimeFormat("en", { era: "hello!" });
  54. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option era");
  55. expect(() => {
  56. new Intl.DateTimeFormat("en", { era: "narrow", dateStyle: "long" });
  57. }).toThrowWithMessage(
  58. TypeError,
  59. "Option era cannot be set when also providing dateStyle or timeStyle"
  60. );
  61. });
  62. test("year option is invalid", () => {
  63. expect(() => {
  64. new Intl.DateTimeFormat("en", { year: "hello!" });
  65. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option year");
  66. expect(() => {
  67. new Intl.DateTimeFormat("en", { year: "numeric", dateStyle: "long" });
  68. }).toThrowWithMessage(
  69. TypeError,
  70. "Option year cannot be set when also providing dateStyle or timeStyle"
  71. );
  72. });
  73. test("month option is invalid", () => {
  74. expect(() => {
  75. new Intl.DateTimeFormat("en", { month: "hello!" });
  76. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option month");
  77. expect(() => {
  78. new Intl.DateTimeFormat("en", { month: "numeric", dateStyle: "long" });
  79. }).toThrowWithMessage(
  80. TypeError,
  81. "Option month cannot be set when also providing dateStyle or timeStyle"
  82. );
  83. });
  84. test("weekday option is invalid", () => {
  85. expect(() => {
  86. new Intl.DateTimeFormat("en", { weekday: "hello!" });
  87. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option weekday");
  88. expect(() => {
  89. new Intl.DateTimeFormat("en", { weekday: "narrow", dateStyle: "long" });
  90. }).toThrowWithMessage(
  91. TypeError,
  92. "Option weekday cannot be set when also providing dateStyle or timeStyle"
  93. );
  94. });
  95. test("day option is invalid", () => {
  96. expect(() => {
  97. new Intl.DateTimeFormat("en", { day: "hello!" });
  98. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option day");
  99. expect(() => {
  100. new Intl.DateTimeFormat("en", { day: "numeric", dateStyle: "long" });
  101. }).toThrowWithMessage(
  102. TypeError,
  103. "Option day cannot be set when also providing dateStyle or timeStyle"
  104. );
  105. });
  106. test("dayPeriod option is invalid", () => {
  107. expect(() => {
  108. new Intl.DateTimeFormat("en", { dayPeriod: "hello!" });
  109. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option dayPeriod");
  110. expect(() => {
  111. new Intl.DateTimeFormat("en", { dayPeriod: "narrow", dateStyle: "long" });
  112. }).toThrowWithMessage(
  113. TypeError,
  114. "Option dayPeriod cannot be set when also providing dateStyle or timeStyle"
  115. );
  116. });
  117. test("hour option is invalid", () => {
  118. expect(() => {
  119. new Intl.DateTimeFormat("en", { hour: "hello!" });
  120. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option hour");
  121. expect(() => {
  122. new Intl.DateTimeFormat("en", { hour: "numeric", dateStyle: "long" });
  123. }).toThrowWithMessage(
  124. TypeError,
  125. "Option hour cannot be set when also providing dateStyle or timeStyle"
  126. );
  127. });
  128. test("minute option is invalid", () => {
  129. expect(() => {
  130. new Intl.DateTimeFormat("en", { minute: "hello!" });
  131. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option minute");
  132. expect(() => {
  133. new Intl.DateTimeFormat("en", { minute: "numeric", dateStyle: "long" });
  134. }).toThrowWithMessage(
  135. TypeError,
  136. "Option minute cannot be set when also providing dateStyle or timeStyle"
  137. );
  138. });
  139. test("second option is invalid", () => {
  140. expect(() => {
  141. new Intl.DateTimeFormat("en", { second: "hello!" });
  142. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option second");
  143. expect(() => {
  144. new Intl.DateTimeFormat("en", { second: "numeric", dateStyle: "long" });
  145. }).toThrowWithMessage(
  146. TypeError,
  147. "Option second cannot be set when also providing dateStyle or timeStyle"
  148. );
  149. });
  150. test("fractionalSecondDigits option is invalid", () => {
  151. expect(() => {
  152. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 1n });
  153. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  154. expect(() => {
  155. new Intl.DateTimeFormat("en", { fractionalSecondDigits: "hello!" });
  156. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 1 and 3");
  157. expect(() => {
  158. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 0 });
  159. }).toThrowWithMessage(RangeError, "Value 0 is NaN or is not between 1 and 3");
  160. expect(() => {
  161. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 4 });
  162. }).toThrowWithMessage(RangeError, "Value 4 is NaN or is not between 1 and 3");
  163. expect(() => {
  164. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 1, dateStyle: "long" });
  165. }).toThrowWithMessage(
  166. TypeError,
  167. "Option fractionalSecondDigits cannot be set when also providing dateStyle or timeStyle"
  168. );
  169. });
  170. test("timeZoneName option is invalid", () => {
  171. expect(() => {
  172. new Intl.DateTimeFormat("en", { timeZoneName: "hello!" });
  173. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option timeZoneName");
  174. expect(() => {
  175. new Intl.DateTimeFormat("en", { timeZoneName: "short", dateStyle: "long" });
  176. }).toThrowWithMessage(
  177. TypeError,
  178. "Option timeZoneName cannot be set when also providing dateStyle or timeStyle"
  179. );
  180. });
  181. test("formatMatcher option is invalid", () => {
  182. expect(() => {
  183. new Intl.DateTimeFormat("en", { formatMatcher: "hello!" });
  184. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option formatMatcher");
  185. });
  186. test("dateStyle option is invalid", () => {
  187. expect(() => {
  188. new Intl.DateTimeFormat("en", { dateStyle: "hello!" });
  189. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option dateStyle");
  190. });
  191. test("timeStyle option is invalid", () => {
  192. expect(() => {
  193. new Intl.DateTimeFormat("en", { timeStyle: "hello!" });
  194. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option timeStyle");
  195. });
  196. });
  197. describe("normal behavior", () => {
  198. test("length is 0", () => {
  199. expect(Intl.DateTimeFormat).toHaveLength(0);
  200. });
  201. test("all valid localeMatcher options", () => {
  202. ["lookup", "best fit"].forEach(localeMatcher => {
  203. expect(() => {
  204. new Intl.DateTimeFormat("en", { localeMatcher: localeMatcher });
  205. }).not.toThrow();
  206. });
  207. });
  208. test("valid calendar options", () => {
  209. ["generic", "gregory"].forEach(calendar => {
  210. expect(() => {
  211. new Intl.DateTimeFormat("en", { calendar: calendar });
  212. }).not.toThrow();
  213. });
  214. });
  215. test("valid numberingSystem options", () => {
  216. ["latn", "arab", "abc-def-ghi"].forEach(numberingSystem => {
  217. expect(() => {
  218. new Intl.DateTimeFormat("en", { numberingSystem: numberingSystem });
  219. }).not.toThrow();
  220. });
  221. });
  222. test("valid hour12 options", () => {
  223. [true, false].forEach(hour12 => {
  224. expect(() => {
  225. new Intl.DateTimeFormat("en", { hour12: hour12 });
  226. }).not.toThrow();
  227. });
  228. });
  229. test("all valid hourCycle options", () => {
  230. ["h11", "h12", "h23", "h24"].forEach(hourCycle => {
  231. expect(() => {
  232. new Intl.DateTimeFormat("en", { hourCycle: hourCycle });
  233. }).not.toThrow();
  234. });
  235. });
  236. test("valid timeZone options", () => {
  237. ["UTC", "EST", "+01:02", "-20:30", "+00:00"].forEach(timeZone => {
  238. expect(() => {
  239. new Intl.DateTimeFormat("en", { timeZone: timeZone });
  240. }).not.toThrow();
  241. });
  242. });
  243. test("all valid weekday options", () => {
  244. ["narrow", "short", "long"].forEach(weekday => {
  245. expect(() => {
  246. new Intl.DateTimeFormat("en", { weekday: weekday });
  247. }).not.toThrow();
  248. });
  249. });
  250. test("all valid era options", () => {
  251. ["narrow", "short", "long"].forEach(era => {
  252. expect(() => {
  253. new Intl.DateTimeFormat("en", { era: era });
  254. }).not.toThrow();
  255. });
  256. });
  257. test("all valid year options", () => {
  258. ["2-digit", "numeric"].forEach(year => {
  259. expect(() => {
  260. new Intl.DateTimeFormat("en", { year: year });
  261. }).not.toThrow();
  262. });
  263. });
  264. test("all valid month options", () => {
  265. ["2-digit", "numeric", "narrow", "short", "long"].forEach(month => {
  266. expect(() => {
  267. new Intl.DateTimeFormat("en", { month: month });
  268. }).not.toThrow();
  269. });
  270. });
  271. test("all valid day options", () => {
  272. ["2-digit", "numeric"].forEach(day => {
  273. expect(() => {
  274. new Intl.DateTimeFormat("en", { day: day });
  275. }).not.toThrow();
  276. });
  277. });
  278. test("all valid dayPeriod options", () => {
  279. ["narrow", "short", "long"].forEach(dayPeriod => {
  280. expect(() => {
  281. new Intl.DateTimeFormat("en", { dayPeriod: dayPeriod });
  282. }).not.toThrow();
  283. });
  284. });
  285. test("all valid hour options", () => {
  286. ["2-digit", "numeric"].forEach(hour => {
  287. expect(() => {
  288. new Intl.DateTimeFormat("en", { hour: hour });
  289. }).not.toThrow();
  290. });
  291. });
  292. test("all valid minute options", () => {
  293. ["2-digit", "numeric"].forEach(minute => {
  294. expect(() => {
  295. new Intl.DateTimeFormat("en", { minute: minute });
  296. }).not.toThrow();
  297. });
  298. });
  299. test("all valid second options", () => {
  300. ["2-digit", "numeric"].forEach(second => {
  301. expect(() => {
  302. new Intl.DateTimeFormat("en", { second: second });
  303. }).not.toThrow();
  304. });
  305. });
  306. test("all valid fractionalSecondDigits options", () => {
  307. [1, 2, 3].forEach(fractionalSecondDigits => {
  308. expect(() => {
  309. new Intl.DateTimeFormat("en", { fractionalSecondDigits: fractionalSecondDigits });
  310. }).not.toThrow();
  311. });
  312. });
  313. test("all valid timeZoneName options", () => {
  314. ["short", "long", "shortOffset", "longOffset", "shortGeneric", "longGeneric"].forEach(
  315. timeZoneName => {
  316. expect(() => {
  317. new Intl.DateTimeFormat("en", { timeZoneName: timeZoneName });
  318. }).not.toThrow();
  319. }
  320. );
  321. });
  322. test("all valid formatMatcher options", () => {
  323. ["basic", "best fit"].forEach(formatMatcher => {
  324. expect(() => {
  325. new Intl.DateTimeFormat("en", { formatMatcher: formatMatcher });
  326. }).not.toThrow();
  327. });
  328. });
  329. test("all valid dateStyle options", () => {
  330. ["full", "long", "medium", "short"].forEach(dateStyle => {
  331. expect(() => {
  332. new Intl.DateTimeFormat("en", { dateStyle: dateStyle });
  333. }).not.toThrow();
  334. });
  335. });
  336. test("all valid timeStyle options", () => {
  337. ["full", "long", "medium", "short"].forEach(timeStyle => {
  338. expect(() => {
  339. new Intl.DateTimeFormat("en", { timeStyle: timeStyle });
  340. }).not.toThrow();
  341. });
  342. });
  343. });