1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16type FormatToPartsResult = [string | undefined, Intl.DateTimeFormatOptions | undefined, Intl.DateTimeRangeFormatPart[]] 17 18const FORMAT_RESULTS = new Array<FormatToPartsResult>() 19 20function addFormatRangeToPartsResult(locale: string | undefined, options: Intl.DateTimeFormatOptions | undefined, result: Intl.DateTimeRangeFormatPart[]): void { 21 const res: [string | undefined, Intl.DateTimeFormatOptions | undefined, Intl.DateTimeRangeFormatPart[]] = [locale, options, result] 22 FORMAT_RESULTS.push(res) 23} 24 25const RANGE_START = new Date("2024-10-11T10:20:30.444Z") 26const RANGE_END = new Date("2024-10-12T20:30:50.444Z") 27 28class RPart implements Intl.DateTimeRangeFormatPart { 29 private _type: Intl.DateTimeFormatPartTypes 30 private _value: string 31 private _source: Intl.DateTimeRangeFormatPartSource 32 33 constructor() { 34 this._type = "literal" 35 this._value = "" 36 this._source = "shared" 37 } 38 39 constructor(type: Intl.DateTimeFormatPartTypes, value: string, source: Intl.DateTimeRangeFormatPartSource) { 40 this._type = type 41 this._value = value 42 this._source = source 43 } 44 45 get type(): Intl.DateTimeFormatPartTypes { 46 return this._type 47 } 48 49 set type(value: Intl.DateTimeFormatPartTypes) { 50 this._type = value 51 } 52 53 get value(): string { 54 return this._value 55 } 56 57 set value(value: string) { 58 this._value = value 59 } 60 61 get source(): Intl.DateTimeRangeFormatPartSource { 62 return this._source 63 } 64 65 set source(source: Intl.DateTimeRangeFormatPartSource) { 66 this._source = source 67 } 68 69 static $_invoke(type: Intl.DateTimeFormatPartTypes, value: string, source: Intl.DateTimeRangeFormatPartSource): RPart { 70 return new RPart(type, value, source) 71 } 72} 73 74function initFormatResults(): void { 75 if (FORMAT_RESULTS.length > 0) { 76 return 77 } 78 79 const resultUS:Intl.DateTimeRangeFormatPart[] = [ 80 RPart("month", "10", "startRange"), RPart("literal", "/", "startRange"), 81 RPart("day", "11", "startRange"), RPart("literal", "/", "startRange"), 82 RPart("year", "2024", "startRange"), RPart("literal", " – ", "shared"), 83 RPart("month", "10", "endRange"), RPart("literal", "/", "endRange"), 84 RPart("day", "12", "endRange"), RPart("literal", "/", "endRange"), 85 RPart("year", "2024", "endRange") 86 ] 87 88 addFormatRangeToPartsResult("en-US", { year: "numeric", month: "2-digit", day: "2-digit", timeZone: "UTC" }, resultUS) 89 90 const resultCN:Intl.DateTimeRangeFormatPart[] = [ 91 RPart("year", "2024", "startRange"), RPart("literal", "/", "startRange"), 92 RPart("month", "10", "startRange"), RPart("literal", "/", "startRange"), 93 RPart("day", "11", "startRange"), RPart("literal", " – ", "shared"), 94 RPart("year", "2024", "endRange"), RPart("literal", "/", "endRange"), 95 RPart("month", "10", "endRange"), RPart("literal", "/", "endRange"), 96 RPart("day", "12", "endRange") 97 ] 98 99 addFormatRangeToPartsResult("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit", timeZone: "UTC" }, resultCN) 100} 101 102function verifyResults(actual: Intl.DateTimeRangeFormatPart[], expected: Intl.DateTimeRangeFormatPart[]): boolean { 103 if (actual.length != expected.length) { 104 return false 105 } 106 107 for (let i = 0; i < actual.length; i++) { 108 const valid = actual[i].type == expected[i].type 109 && actual[i].value == expected[i].value 110 && actual[i].source == expected[i].source 111 112 if (!valid) { 113 return false 114 } 115 } 116 117 return true 118} 119 120function dateFormatToPartsWithOptions(): void { 121 FORMAT_RESULTS.forEach((res: FormatToPartsResult) => { 122 const locale = res[0] 123 const options = res[1] 124 125 const formatter = new Intl.DateTimeFormat(locale, options) 126 const actualResult = formatter.formatRangeToParts(RANGE_START, RANGE_END) 127 const expectedResult = res[2] 128 129 const resultIsValid = verifyResults(actualResult, expectedResult); 130 if (!resultIsValid) { 131 const range = `${RANGE_START}, ${RANGE_END}` 132 const failMsg = `Unexpected DateTimeFormat(${locale}, ${options}).formatRangeToParts(${range}) result` 133 assertTrue(false, failMsg) 134 } 135 }) 136} 137 138function main(): int { 139 initFormatResults() 140 141 const suite = new ArkTestsuite("Intl.DateTimeFormat.formatToParts()") 142 suite.addTest("with formatting options", dateFormatToPartsWithOptions) 143 return suite.run() 144} 145