From 2f33727923fa3472be8bd5d269017b8fdc28e1eb Mon Sep 17 00:00:00 2001 From: mildgravitas <10595307+mildgravitas@users.noreply.github.com> Date: Wed, 23 Feb 2022 23:45:07 +0100 Subject: [PATCH 1/5] WeekOf provider (#1366) - Adds regional preference data for week info. --- components/calendar/src/arithmetic.rs | 14 + components/calendar/src/types.rs | 4 + components/datetime/Cargo.toml | 2 +- components/datetime/src/date.rs | 58 +- components/datetime/src/datetime.rs | 4 +- components/datetime/src/format/datetime.rs | 102 ++-- .../datetime/src/format/zoned_datetime.rs | 10 +- components/datetime/src/provider/mod.rs | 3 + components/datetime/src/provider/week_data.rs | 15 + components/datetime/src/raw/datetime.rs | 39 +- components/datetime/src/raw/zoned_datetime.rs | 29 +- components/datetime/src/zoned_datetime.rs | 4 +- components/datetime/tests/datetime.rs | 38 +- .../tests/components-exact-matches.json | 24 +- .../tests/components-partial-matches.json | 3 +- .../tests/components-width-differences.json | 10 +- .../fixtures/tests/components_with_zones.json | 7 +- provider/cldr/src/cldr_serde/mod.rs | 1 + provider/cldr/src/cldr_serde/week_data.rs | 134 +++++ provider/cldr/src/lib.rs | 6 +- provider/cldr/src/transform/datetime/mod.rs | 1 + .../cldr/src/transform/datetime/week_data.rs | 199 ++++++ provider/testdata/Cargo.toml | 1 + .../cldr/cldr-core/supplemental/weekData.json | 569 ++++++++++++++++++ .../data/json/datetime/week_data@1.json | 4 + .../data/json/datetime/week_data@1/AD.json | 4 + .../data/json/datetime/week_data@1/AE.json | 4 + .../data/json/datetime/week_data@1/AF.json | 4 + .../data/json/datetime/week_data@1/AG.json | 4 + .../data/json/datetime/week_data@1/AI.json | 4 + .../data/json/datetime/week_data@1/AL.json | 4 + .../data/json/datetime/week_data@1/AM.json | 4 + .../data/json/datetime/week_data@1/AN.json | 4 + .../data/json/datetime/week_data@1/AR.json | 4 + .../data/json/datetime/week_data@1/AS.json | 4 + .../data/json/datetime/week_data@1/AT.json | 4 + .../data/json/datetime/week_data@1/AU.json | 4 + .../data/json/datetime/week_data@1/AX.json | 4 + .../data/json/datetime/week_data@1/AZ.json | 4 + .../data/json/datetime/week_data@1/BA.json | 4 + .../data/json/datetime/week_data@1/BD.json | 4 + .../data/json/datetime/week_data@1/BE.json | 4 + .../data/json/datetime/week_data@1/BG.json | 4 + .../data/json/datetime/week_data@1/BH.json | 4 + .../data/json/datetime/week_data@1/BM.json | 4 + .../data/json/datetime/week_data@1/BN.json | 4 + .../data/json/datetime/week_data@1/BR.json | 4 + .../data/json/datetime/week_data@1/BS.json | 4 + .../data/json/datetime/week_data@1/BT.json | 4 + .../data/json/datetime/week_data@1/BW.json | 4 + .../data/json/datetime/week_data@1/BY.json | 4 + .../data/json/datetime/week_data@1/BZ.json | 4 + .../data/json/datetime/week_data@1/CA.json | 4 + .../data/json/datetime/week_data@1/CH.json | 4 + .../data/json/datetime/week_data@1/CL.json | 4 + .../data/json/datetime/week_data@1/CM.json | 4 + .../data/json/datetime/week_data@1/CN.json | 4 + .../data/json/datetime/week_data@1/CO.json | 4 + .../data/json/datetime/week_data@1/CR.json | 4 + .../data/json/datetime/week_data@1/CY.json | 4 + .../data/json/datetime/week_data@1/CZ.json | 4 + .../data/json/datetime/week_data@1/DE.json | 4 + .../data/json/datetime/week_data@1/DJ.json | 4 + .../data/json/datetime/week_data@1/DK.json | 4 + .../data/json/datetime/week_data@1/DM.json | 4 + .../data/json/datetime/week_data@1/DO.json | 4 + .../data/json/datetime/week_data@1/DZ.json | 4 + .../data/json/datetime/week_data@1/EC.json | 4 + .../data/json/datetime/week_data@1/EE.json | 4 + .../data/json/datetime/week_data@1/EG.json | 4 + .../data/json/datetime/week_data@1/ES.json | 4 + .../data/json/datetime/week_data@1/ET.json | 4 + .../data/json/datetime/week_data@1/FI.json | 4 + .../data/json/datetime/week_data@1/FJ.json | 4 + .../data/json/datetime/week_data@1/FO.json | 4 + .../data/json/datetime/week_data@1/FR.json | 4 + .../data/json/datetime/week_data@1/GB.json | 4 + .../data/json/datetime/week_data@1/GE.json | 4 + .../data/json/datetime/week_data@1/GF.json | 4 + .../data/json/datetime/week_data@1/GG.json | 4 + .../data/json/datetime/week_data@1/GI.json | 4 + .../data/json/datetime/week_data@1/GP.json | 4 + .../data/json/datetime/week_data@1/GR.json | 4 + .../data/json/datetime/week_data@1/GT.json | 4 + .../data/json/datetime/week_data@1/GU.json | 4 + .../data/json/datetime/week_data@1/HK.json | 4 + .../data/json/datetime/week_data@1/HN.json | 4 + .../data/json/datetime/week_data@1/HR.json | 4 + .../data/json/datetime/week_data@1/HU.json | 4 + .../data/json/datetime/week_data@1/ID.json | 4 + .../data/json/datetime/week_data@1/IE.json | 4 + .../data/json/datetime/week_data@1/IL.json | 4 + .../data/json/datetime/week_data@1/IM.json | 4 + .../data/json/datetime/week_data@1/IN.json | 4 + .../data/json/datetime/week_data@1/IQ.json | 4 + .../data/json/datetime/week_data@1/IR.json | 4 + .../data/json/datetime/week_data@1/IS.json | 4 + .../data/json/datetime/week_data@1/IT.json | 4 + .../data/json/datetime/week_data@1/JE.json | 4 + .../data/json/datetime/week_data@1/JM.json | 4 + .../data/json/datetime/week_data@1/JO.json | 4 + .../data/json/datetime/week_data@1/JP.json | 4 + .../data/json/datetime/week_data@1/KE.json | 4 + .../data/json/datetime/week_data@1/KG.json | 4 + .../data/json/datetime/week_data@1/KH.json | 4 + .../data/json/datetime/week_data@1/KR.json | 4 + .../data/json/datetime/week_data@1/KW.json | 4 + .../data/json/datetime/week_data@1/KZ.json | 4 + .../data/json/datetime/week_data@1/LA.json | 4 + .../data/json/datetime/week_data@1/LB.json | 4 + .../data/json/datetime/week_data@1/LI.json | 4 + .../data/json/datetime/week_data@1/LK.json | 4 + .../data/json/datetime/week_data@1/LT.json | 4 + .../data/json/datetime/week_data@1/LU.json | 4 + .../data/json/datetime/week_data@1/LV.json | 4 + .../data/json/datetime/week_data@1/LY.json | 4 + .../data/json/datetime/week_data@1/MC.json | 4 + .../data/json/datetime/week_data@1/MD.json | 4 + .../data/json/datetime/week_data@1/ME.json | 4 + .../data/json/datetime/week_data@1/MH.json | 4 + .../data/json/datetime/week_data@1/MK.json | 4 + .../data/json/datetime/week_data@1/MM.json | 4 + .../data/json/datetime/week_data@1/MN.json | 4 + .../data/json/datetime/week_data@1/MO.json | 4 + .../data/json/datetime/week_data@1/MQ.json | 4 + .../data/json/datetime/week_data@1/MT.json | 4 + .../data/json/datetime/week_data@1/MV.json | 4 + .../data/json/datetime/week_data@1/MX.json | 4 + .../data/json/datetime/week_data@1/MY.json | 4 + .../data/json/datetime/week_data@1/MZ.json | 4 + .../data/json/datetime/week_data@1/NI.json | 4 + .../data/json/datetime/week_data@1/NL.json | 4 + .../data/json/datetime/week_data@1/NO.json | 4 + .../data/json/datetime/week_data@1/NP.json | 4 + .../data/json/datetime/week_data@1/NZ.json | 4 + .../data/json/datetime/week_data@1/OM.json | 4 + .../data/json/datetime/week_data@1/PA.json | 4 + .../data/json/datetime/week_data@1/PE.json | 4 + .../data/json/datetime/week_data@1/PH.json | 4 + .../data/json/datetime/week_data@1/PK.json | 4 + .../data/json/datetime/week_data@1/PL.json | 4 + .../data/json/datetime/week_data@1/PR.json | 4 + .../data/json/datetime/week_data@1/PT.json | 4 + .../data/json/datetime/week_data@1/PY.json | 4 + .../data/json/datetime/week_data@1/QA.json | 4 + .../data/json/datetime/week_data@1/RE.json | 4 + .../data/json/datetime/week_data@1/RO.json | 4 + .../data/json/datetime/week_data@1/RS.json | 4 + .../data/json/datetime/week_data@1/RU.json | 4 + .../data/json/datetime/week_data@1/SA.json | 4 + .../data/json/datetime/week_data@1/SD.json | 4 + .../data/json/datetime/week_data@1/SE.json | 4 + .../data/json/datetime/week_data@1/SG.json | 4 + .../data/json/datetime/week_data@1/SI.json | 4 + .../data/json/datetime/week_data@1/SJ.json | 4 + .../data/json/datetime/week_data@1/SK.json | 4 + .../data/json/datetime/week_data@1/SM.json | 4 + .../data/json/datetime/week_data@1/SV.json | 4 + .../data/json/datetime/week_data@1/SY.json | 4 + .../data/json/datetime/week_data@1/TH.json | 4 + .../data/json/datetime/week_data@1/TJ.json | 4 + .../data/json/datetime/week_data@1/TM.json | 4 + .../data/json/datetime/week_data@1/TR.json | 4 + .../data/json/datetime/week_data@1/TT.json | 4 + .../data/json/datetime/week_data@1/TW.json | 4 + .../data/json/datetime/week_data@1/UA.json | 4 + .../data/json/datetime/week_data@1/UM.json | 4 + .../data/json/datetime/week_data@1/US.json | 4 + .../data/json/datetime/week_data@1/UY.json | 4 + .../data/json/datetime/week_data@1/UZ.json | 4 + .../data/json/datetime/week_data@1/VA.json | 4 + .../data/json/datetime/week_data@1/VE.json | 4 + .../data/json/datetime/week_data@1/VI.json | 4 + .../data/json/datetime/week_data@1/VN.json | 4 + .../data/json/datetime/week_data@1/WS.json | 4 + .../data/json/datetime/week_data@1/XK.json | 4 + .../data/json/datetime/week_data@1/YE.json | 4 + .../data/json/datetime/week_data@1/ZA.json | 4 + .../data/json/datetime/week_data@1/ZW.json | 4 + provider/testdata/data/testdata.postcard | Bin 1670502 -> 1672368 bytes .../datagen/tests/testdata/work_log+keys.txt | 1 + 181 files changed, 1789 insertions(+), 109 deletions(-) create mode 100644 components/datetime/src/provider/week_data.rs create mode 100644 provider/cldr/src/cldr_serde/week_data.rs create mode 100644 provider/cldr/src/transform/datetime/week_data.rs create mode 100644 provider/testdata/data/cldr/cldr-core/supplemental/weekData.json create mode 100644 provider/testdata/data/json/datetime/week_data@1.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AD.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AF.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AG.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AL.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AS.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AU.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AX.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/AZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BD.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BG.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BH.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BS.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BW.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/BZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CH.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CL.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/CZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/DE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/DJ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/DK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/DM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/DO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/DZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/EC.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/EE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/EG.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/ES.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/ET.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/FI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/FJ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/FO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/FR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GB.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GF.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GG.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GP.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/GU.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/HK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/HN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/HR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/HU.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/ID.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IL.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IQ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IS.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/IT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/JE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/JM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/JO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/JP.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/KE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/KG.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/KH.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/KR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/KW.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/KZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LB.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LU.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LV.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/LY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MC.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MD.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/ME.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MH.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MQ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MV.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MX.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/MZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/NI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/NL.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/NO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/NP.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/NZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/OM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PH.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PL.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/PY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/QA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/RE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/RO.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/RS.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/RU.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SD.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SG.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SJ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SV.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/SY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/TH.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/TJ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/TM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/TR.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/TT.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/TW.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/UA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/UM.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/US.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/UY.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/UZ.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/VA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/VE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/VI.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/VN.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/WS.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/XK.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/YE.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/ZA.json create mode 100644 provider/testdata/data/json/datetime/week_data@1/ZW.json diff --git a/components/calendar/src/arithmetic.rs b/components/calendar/src/arithmetic.rs index 79f313c5d6b..33522c63b27 100644 --- a/components/calendar/src/arithmetic.rs +++ b/components/calendar/src/arithmetic.rs @@ -9,6 +9,11 @@ pub mod week_of { pub const MIN_UNIT_DAYS: u16 = 14; /// Information about how a given calendar assigns weeks to a year or month. + #[derive(Clone, Copy, Debug)] + #[cfg_attr( + feature = "provider_serde", + derive(serde::Serialize, serde::Deserialize) + )] pub struct CalendarInfo { /// The first day of a week. pub first_weekday: IsoWeekday, @@ -23,6 +28,15 @@ pub mod week_of { } } + impl Default for CalendarInfo { + fn default() -> Self { + Self { + first_weekday: IsoWeekday::Monday, + min_week_days: 1, + } + } + } + /// Returns the weekday that's `num_days` after `weekday`. fn add_to_weekday(weekday: IsoWeekday, num_days: i32) -> IsoWeekday { let new_weekday = (7 + (weekday as i32) + (num_days % 7)) % 7; diff --git a/components/calendar/src/types.rs b/components/calendar/src/types.rs index 788d163506e..927161994f4 100644 --- a/components/calendar/src/types.rs +++ b/components/calendar/src/types.rs @@ -356,6 +356,10 @@ impl FromStr for GmtOffset { #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[allow(missing_docs)] // The weekday variants should be self-obvious. #[repr(i8)] +#[cfg_attr( + feature = "provider_serde", + derive(serde::Serialize, serde::Deserialize) +)] pub enum IsoWeekday { Monday = 1, Tuesday, diff --git a/components/datetime/Cargo.toml b/components/datetime/Cargo.toml index b6e922c6280..d38b6842db4 100644 --- a/components/datetime/Cargo.toml +++ b/components/datetime/Cargo.toml @@ -67,7 +67,7 @@ bench = false # This option is required for Benchmark CI std = ["icu_provider/std", "icu_locid/std", "icu_calendar/std"] default = ["provider_serde"] bench = [] -provider_serde = ["serde", "litemap/serde_serialize", "smallvec/serde", "litemap/serde", "zerovec/serde", "tinystr/serde", "icu_provider/serde"] +provider_serde = ["serde", "litemap/serde_serialize", "smallvec/serde", "litemap/serde", "zerovec/serde", "tinystr/serde", "icu_calendar/provider_serde", "icu_provider/serde"] provider_transform_internals = ["std"] [[bench]] diff --git a/components/datetime/src/date.rs b/components/datetime/src/date.rs index 31553ba4b63..28e09ae31e8 100644 --- a/components/datetime/src/date.rs +++ b/components/datetime/src/date.rs @@ -117,7 +117,7 @@ pub trait LocalizedDateTimeInput { pub(crate) struct DateTimeInputWithLocale<'data, T: DateTimeInput> { data: &'data T, - calendar: week_of::CalendarInfo, + calendar: Option<&'data week_of::CalendarInfo>, } fn compute_week_of_year( @@ -164,33 +164,27 @@ fn week_of_year( } impl<'data, T: DateTimeInput> DateTimeInputWithLocale<'data, T> { - pub fn new(data: &'data T, _locale: &Locale) -> Self { - Self { - data, - // TODO(#488): Implement week calculations. - calendar: week_of::CalendarInfo { - first_weekday: IsoWeekday::Monday, - min_week_days: 4, - }, - } + pub fn new( + data: &'data T, + calendar: Option<&'data week_of::CalendarInfo>, + _locale: &Locale, + ) -> Self { + Self { data, calendar } } } pub(crate) struct ZonedDateTimeInputWithLocale<'data, T: ZonedDateTimeInput> { data: &'data T, - calendar: week_of::CalendarInfo, + calendar: Option<&'data week_of::CalendarInfo>, } impl<'data, T: ZonedDateTimeInput> ZonedDateTimeInputWithLocale<'data, T> { - pub fn new(data: &'data T, _locale: &Locale) -> Self { - Self { - data, - // TODO(#488): Implement week calculations. - calendar: week_of::CalendarInfo { - first_weekday: IsoWeekday::Monday, - min_week_days: 4, - }, - } + pub fn new( + data: &'data T, + calendar: Option<&'data week_of::CalendarInfo>, + _locale: &Locale, + ) -> Self { + Self { data, calendar } } } @@ -200,7 +194,11 @@ impl<'data, T: DateTimeInput> LocalizedDateTimeInput for DateTimeInputWithLoc } fn year_week(&self) -> Result { - year_week(self.data, &self.calendar) + year_week( + self.data, + self.calendar + .expect("calendar must be provided when using week of methods"), + ) } fn week_of_month(&self) -> WeekOfMonth { @@ -208,7 +206,11 @@ impl<'data, T: DateTimeInput> LocalizedDateTimeInput for DateTimeInputWithLoc } fn week_of_year(&self) -> Result { - week_of_year(self.data, &self.calendar) + week_of_year( + self.data, + self.calendar + .expect("calendar must be provided when using week of methods"), + ) } fn flexible_day_period(&self) { @@ -224,7 +226,11 @@ impl<'data, T: ZonedDateTimeInput> LocalizedDateTimeInput } fn year_week(&self) -> Result { - year_week(self.data, &self.calendar) + year_week( + self.data, + self.calendar + .expect("calendar must be provided when using week of methods"), + ) } fn week_of_month(&self) -> WeekOfMonth { @@ -232,7 +238,11 @@ impl<'data, T: ZonedDateTimeInput> LocalizedDateTimeInput } fn week_of_year(&self) -> Result { - week_of_year(self.data, &self.calendar) + week_of_year( + self.data, + self.calendar + .expect("calendar must be provided when using week of methods"), + ) } fn flexible_day_period(&self) { diff --git a/components/datetime/src/datetime.rs b/components/datetime/src/datetime.rs index 0dd2ea5002e..7576cb42694 100644 --- a/components/datetime/src/datetime.rs +++ b/components/datetime/src/datetime.rs @@ -8,6 +8,7 @@ use crate::{ options::{components, DateTimeFormatOptions}, provider::calendar::{DatePatternsV1Marker, DateSkeletonPatternsV1Marker, DateSymbolsV1Marker}, + provider::week_data::WeekDataV1Marker, raw, }; use alloc::string::String; @@ -96,7 +97,8 @@ impl DateTimeFormat { D: ResourceProvider + ResourceProvider + ResourceProvider - + ResourceProvider, + + ResourceProvider + + ResourceProvider, { Ok(Self( raw::DateTimeFormat::try_new(locale, data_provider, options, C::IDENTIFIER)?, diff --git a/components/datetime/src/format/datetime.rs b/components/datetime/src/format/datetime.rs index 729af765706..5f4714b4dba 100644 --- a/components/datetime/src/format/datetime.rs +++ b/components/datetime/src/format/datetime.rs @@ -12,6 +12,7 @@ use crate::pattern::{ use crate::provider; use crate::provider::calendar::patterns::PatternPluralsFromPatternsV1Marker; use crate::provider::date_time::DateTimeSymbols; +use crate::provider::week_data::WeekDataV1; use alloc::string::ToString; use core::fmt; @@ -55,6 +56,7 @@ where pub(crate) patterns: &'l DataPayload, pub(crate) symbols: Option<&'l provider::calendar::DateSymbolsV1<'l>>, pub(crate) datetime: &'l T, + pub(crate) week_data: Option<&'l WeekDataV1>, pub(crate) locale: &'l Locale, pub(crate) ordinal_rules: Option<&'l PluralRules>, } @@ -68,6 +70,7 @@ where &self.patterns.get().0, self.symbols, self.datetime, + self.week_data, self.ordinal_rules, self.locale, sink, @@ -130,6 +133,7 @@ pub fn write_pattern_plurals( patterns: &PatternPlurals, symbols: Option<&provider::calendar::DateSymbolsV1>, datetime: &T, + week_data: Option<&WeekDataV1>, ordinal_rules: Option<&PluralRules>, locale: &Locale, w: &mut W, @@ -138,7 +142,7 @@ where T: DateTimeInput, W: fmt::Write + ?Sized, { - let loc_datetime = DateTimeInputWithLocale::new(datetime, locale); + let loc_datetime = DateTimeInputWithLocale::new(datetime, week_data.map(|d| &d.0), locale); let pattern = patterns.select(&loc_datetime, ordinal_rules)?; write_pattern(pattern, symbols, &loc_datetime, w) } @@ -298,58 +302,84 @@ where Ok(()) } -// This function determins whether the struct will load symbols data. -// Keep it in sync with the `write_field` use of symbols. -pub fn analyze_pattern(pattern: &Pattern, supports_time_zones: bool) -> Result { - let fields = pattern.items.iter().filter_map(|p| match p { - PatternItem::Field(field) => Some(field), - _ => None, - }); +/// What data is required to format a given pattern. +#[derive(Default)] +pub struct RequiredData { + // DateSymbolsV1 is required. + pub symbols_data: bool, + // WeekDataV1 is required. + pub week_data: bool, +} - let mut requires_symbols = false; +impl RequiredData { + // Checks if formatting `pattern` would require us to load data & if so adds + // them to this struct. Returns true if requirements are saturated and would + // not change by any further calls. + // Keep it in sync with the `write_field` use of symbols. + fn add_requirements_from_pattern( + &mut self, + pattern: &Pattern, + supports_time_zones: bool, + ) -> Result { + let fields = pattern.items.iter().filter_map(|p| match p { + PatternItem::Field(field) => Some(field), + _ => None, + }); - for field in fields { - if !requires_symbols { - requires_symbols = match field.symbol { - FieldSymbol::Era => true, - FieldSymbol::Month(_) => { - !matches!(field.length, FieldLength::One | FieldLength::TwoDigit) + for field in fields { + if !self.symbols_data { + self.symbols_data = match field.symbol { + FieldSymbol::Era => true, + FieldSymbol::Month(_) => { + !matches!(field.length, FieldLength::One | FieldLength::TwoDigit) + } + FieldSymbol::Weekday(_) | FieldSymbol::DayPeriod(_) => true, + _ => false, } - FieldSymbol::Weekday(_) | FieldSymbol::DayPeriod(_) => true, - _ => false, } - } + if !self.week_data { + self.week_data = matches!( + field.symbol, + FieldSymbol::Year(Year::WeekOf) | FieldSymbol::Week(_) + ) + } - if supports_time_zones { - if requires_symbols { - // If we require time zones, and symbols, we know all - // we need to return already. - break; + if supports_time_zones { + if self.symbols_data && self.week_data { + // If we support time zones, and require everything else, we + // know all we need to return already. + return Ok(true); + } + } else if matches!(field.symbol, FieldSymbol::TimeZone(_)) { + // If we don't support time zones, and encountered a time zone + // field, error out. + return Err(field); } - } else if matches!(field.symbol, FieldSymbol::TimeZone(_)) { - // If we don't support time zones, and encountered a time zone - // field, error out. - return Err(field); } - } - Ok(requires_symbols) + Ok(false) + } } -// This function determines whether any patterns will load symbols data. +// Determines what optional data needs to be loaded to format `patterns`. pub fn analyze_patterns( patterns: &PatternPlurals, supports_time_zones: bool, -) -> Result { - patterns.patterns_iter().try_fold(false, |a, pattern| { - analyze_pattern(pattern, supports_time_zones).map(|b| a || b) - }) +) -> Result { + let mut required = RequiredData::default(); + for pattern in patterns.patterns_iter() { + if required.add_requirements_from_pattern(pattern, supports_time_zones)? { + // We can bail early if everything is required & we don't need to + // validate the absence of TimeZones. + break; + } + } + Ok(required) } #[cfg(test)] mod tests { use super::*; - #[test] #[cfg(feature = "provider_serde")] fn test_basic() { @@ -373,7 +403,7 @@ mod tests { let datetime = DateTime::new_gregorian_datetime_from_integers(2020, 8, 1, 12, 34, 28).unwrap(); let mut sink = String::new(); - let loc_datetime = DateTimeInputWithLocale::new(&datetime, &"und".parse().unwrap()); + let loc_datetime = DateTimeInputWithLocale::new(&datetime, None, &"und".parse().unwrap()); write_pattern(&pattern, Some(data.get()), &loc_datetime, &mut sink).unwrap(); println!("{}", sink); } diff --git a/components/datetime/src/format/zoned_datetime.rs b/components/datetime/src/format/zoned_datetime.rs index d344e76dcbd..92bfbd09306 100644 --- a/components/datetime/src/format/zoned_datetime.rs +++ b/components/datetime/src/format/zoned_datetime.rs @@ -58,7 +58,15 @@ where { let locale = &zoned_datetime_format.datetime_format.locale; let patterns = &zoned_datetime_format.datetime_format.patterns; - let loc_datetime = ZonedDateTimeInputWithLocale::new(zoned_datetime, locale); + let loc_datetime = ZonedDateTimeInputWithLocale::new( + zoned_datetime, + zoned_datetime_format + .datetime_format + .week_data + .as_ref() + .map(|d| &d.get().0), + locale, + ); let pattern = patterns.get().0.select( &loc_datetime, diff --git a/components/datetime/src/provider/mod.rs b/components/datetime/src/provider/mod.rs index 9d9780307a1..60c63c8aa8d 100644 --- a/components/datetime/src/provider/mod.rs +++ b/components/datetime/src/provider/mod.rs @@ -15,5 +15,8 @@ pub mod calendar; /// Data providers for time zones. pub mod time_zones; +/// Provider for week data. +pub mod week_data; + /// Traits for managing data needed by [`DateTimeFormat`](crate::DateTimeFormat). pub(crate) mod date_time; diff --git a/components/datetime/src/provider/week_data.rs b/components/datetime/src/provider/week_data.rs new file mode 100644 index 00000000000..8351369ba43 --- /dev/null +++ b/components/datetime/src/provider/week_data.rs @@ -0,0 +1,15 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use icu_provider::prelude::*; + +/// An ICU4X mapping to a subset of CLDR weekData. +/// See CLDR-JSON's weekData.json for more context. +#[icu_provider::data_struct(WeekDataV1Marker = "datetime/week_data@1")] +#[derive(Clone, Copy, Default)] +#[cfg_attr( + feature = "provider_serde", + derive(serde::Serialize, serde::Deserialize) +)] +pub struct WeekDataV1(pub icu_calendar::arithmetic::week_of::CalendarInfo); diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index 08ea6ebf45b..ace2e49f984 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -11,8 +11,9 @@ use crate::{ options::DateTimeFormatOptions, provider::calendar::patterns::PatternPluralsFromPatternsV1Marker, provider::calendar::{DatePatternsV1Marker, DateSkeletonPatternsV1Marker, DateSymbolsV1Marker}, + provider::week_data::WeekDataV1Marker, }; -use alloc::string::String; +use alloc::string::{String, ToString}; use icu_locid::Locale; use icu_plurals::{provider::OrdinalV1Marker, PluralRules}; use icu_provider::prelude::*; @@ -28,6 +29,7 @@ pub(crate) struct DateTimeFormat { pub locale: Locale, pub patterns: DataPayload, pub symbols: Option>, + pub week_data: Option>, pub ordinal_rules: Option, } @@ -47,7 +49,8 @@ impl DateTimeFormat { D: ResourceProvider + ResourceProvider + ResourceProvider - + ResourceProvider, + + ResourceProvider + + ResourceProvider, { let locale = locale.into(); @@ -58,18 +61,34 @@ impl DateTimeFormat { calendar, )?; - let requires_data = datetime::analyze_patterns(&patterns.get().0, false) + let required = datetime::analyze_patterns(&patterns.get().0, false) .map_err(|field| DateTimeFormatError::UnsupportedField(field.symbol))?; let langid: icu_locid::LanguageIdentifier = locale.clone().into(); + let week_data = if required.week_data { + Some( + data_provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: langid.region.map(|r| r.as_str().to_string().into()), + langid: None, + }, + metadata: Default::default(), + })? + .take_payload()?, + ) + } else { + None + }; + let ordinal_rules = if let PatternPlurals::MultipleVariants(_) = &patterns.get().0 { Some(PluralRules::try_new_ordinal(locale.clone(), data_provider)?) } else { None }; - let symbols_data = if requires_data { + let symbols_data = if required.symbols_data { Some( data_provider .load_resource(&DataRequest { @@ -85,7 +104,13 @@ impl DateTimeFormat { None }; - Ok(Self::new(locale, patterns, symbols_data, ordinal_rules)) + Ok(Self::new( + locale, + patterns, + symbols_data, + week_data, + ordinal_rules, + )) } /// Creates a new [`DateTimeFormat`] regardless of whether there are time-zone symbols in the pattern. @@ -93,6 +118,7 @@ impl DateTimeFormat { locale: T, patterns: DataPayload, symbols: Option>, + week_data: Option>, ordinal_rules: Option, ) -> Self { let locale = locale.into(); @@ -101,6 +127,7 @@ impl DateTimeFormat { locale, patterns, symbols, + week_data, ordinal_rules, } } @@ -116,6 +143,7 @@ impl DateTimeFormat { patterns: &self.patterns, symbols: self.symbols.as_ref().map(|s| s.get()), datetime: value, + week_data: self.week_data.as_ref().map(|s| s.get()), locale: &self.locale, ordinal_rules: self.ordinal_rules.as_ref(), } @@ -133,6 +161,7 @@ impl DateTimeFormat { &self.patterns.get().0, self.symbols.as_ref().map(|s| s.get()), value, + self.week_data.as_ref().map(|s| s.get()), self.ordinal_rules.as_ref(), &self.locale, w, diff --git a/components/datetime/src/raw/zoned_datetime.rs b/components/datetime/src/raw/zoned_datetime.rs index 055038f2976..7e403907c62 100644 --- a/components/datetime/src/raw/zoned_datetime.rs +++ b/components/datetime/src/raw/zoned_datetime.rs @@ -2,7 +2,7 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use alloc::string::String; +use alloc::string::{String, ToString}; use icu_locid::{LanguageIdentifier, Locale}; use icu_plurals::{provider::OrdinalV1Marker, PluralRules}; use icu_provider::prelude::*; @@ -18,6 +18,7 @@ use crate::{ provider::{ self, calendar::{DatePatternsV1Marker, DateSkeletonPatternsV1Marker, DateSymbolsV1Marker}, + week_data::WeekDataV1Marker, }, raw, time_zone::TimeZoneFormat, @@ -50,7 +51,8 @@ impl ZonedDateTimeFormat { L: Into, DP: ResourceProvider + ResourceProvider - + ResourceProvider, + + ResourceProvider + + ResourceProvider, ZP: ResourceProvider + ResourceProvider + ResourceProvider @@ -69,10 +71,25 @@ impl ZonedDateTimeFormat { options, calendar, )?; - - let requires_data = datetime::analyze_patterns(&patterns.get().0, true) + let required = datetime::analyze_patterns(&patterns.get().0, true) .map_err(|field| DateTimeFormatError::UnsupportedField(field.symbol))?; + let week_data = if required.week_data { + Some( + date_provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: langid.region.map(|r| r.as_str().to_string().into()), + langid: None, + }, + metadata: Default::default(), + })? + .take_payload()?, + ) + } else { + None + }; + let ordinal_rules = if let PatternPlurals::MultipleVariants(_) = &patterns.get().0 { Some(PluralRules::try_new_ordinal( locale.clone(), @@ -82,7 +99,7 @@ impl ZonedDateTimeFormat { None }; - let symbols_data = if requires_data { + let symbols_data = if required.symbols_data { Some( date_provider .load_resource(&DataRequest { @@ -99,7 +116,7 @@ impl ZonedDateTimeFormat { }; let datetime_format = - raw::DateTimeFormat::new(locale, patterns, symbols_data, ordinal_rules); + raw::DateTimeFormat::new(locale, patterns, symbols_data, week_data, ordinal_rules); let time_zone_format = TimeZoneFormat::try_new( datetime_format.locale.clone(), datetime_format diff --git a/components/datetime/src/zoned_datetime.rs b/components/datetime/src/zoned_datetime.rs index 44e198102a7..075a4c681e4 100644 --- a/components/datetime/src/zoned_datetime.rs +++ b/components/datetime/src/zoned_datetime.rs @@ -15,6 +15,7 @@ use crate::{ provider::{ self, calendar::{DatePatternsV1Marker, DateSkeletonPatternsV1Marker, DateSymbolsV1Marker}, + week_data::WeekDataV1Marker, }, raw, CldrCalendar, DateTimeFormatError, }; @@ -106,7 +107,8 @@ impl ZonedDateTimeFormat { L: Into, DP: ResourceProvider + ResourceProvider - + ResourceProvider, + + ResourceProvider + + ResourceProvider, ZP: ResourceProvider + ResourceProvider + ResourceProvider diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index 9900307ebfe..982fa8b3d07 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -11,7 +11,10 @@ use icu_calendar::{buddhist::Buddhist, japanese::Japanese, AsCalendar, DateTime, use icu_datetime::{ mock::{parse_gregorian_from_str, zoned_datetime::MockZonedDateTime}, pattern::runtime::Pattern, - provider::calendar::{DatePatternsV1Marker, DateSkeletonPatternsV1Marker, DateSymbolsV1Marker}, + provider::{ + calendar::{DatePatternsV1Marker, DateSkeletonPatternsV1Marker, DateSymbolsV1Marker}, + week_data::WeekDataV1Marker, + }, time_zone::TimeZoneFormat, CldrCalendar, DateTimeFormat, DateTimeFormatOptions, ZonedDateTimeFormat, }; @@ -98,7 +101,8 @@ fn assert_fixture_element( D: ResourceProvider + ResourceProvider + ResourceProvider - + ResourceProvider, + + ResourceProvider + + ResourceProvider, { let locale: Locale = locale.parse().unwrap(); let dtf = DateTimeFormat::::try_new(locale, provider, options).unwrap(); @@ -209,6 +213,17 @@ fn test_dayperiod_patterns() { .unwrap() .take_payload() .unwrap(); + let week_data: DataPayload = provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: langid.region.map(|r| r.as_str().to_string().into()), + langid: None, + }, + metadata: Default::default(), + }) + .unwrap() + .take_payload() + .unwrap(); for test_case in &test.test_cases { for dt_input in &test_case.datetimes { let datetime = parse_gregorian_from_str(dt_input).unwrap(); @@ -234,6 +249,10 @@ fn test_dayperiod_patterns() { key: DatePatternsV1Marker::KEY, data: patterns_data.clone().wrap_into_any_payload(), }, + AnyPayloadProvider { + key: WeekDataV1Marker::KEY, + data: week_data.clone().wrap_into_any_payload(), + }, ], }; let dtf = DateTimeFormat::::try_new( @@ -351,6 +370,17 @@ fn test_time_zone_patterns() { .unwrap() .take_payload() .unwrap(); + let week_data: DataPayload = date_provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: langid.region.map(|r| r.as_str().to_string().into()), + langid: None, + }, + metadata: Default::default(), + }) + .unwrap() + .take_payload() + .unwrap(); patterns_data.with_mut(|data| { data.length_combinations.long = "{0}".parse().unwrap(); @@ -383,6 +413,10 @@ fn test_time_zone_patterns() { key: DatePatternsV1Marker::KEY, data: patterns_data.clone().wrap_into_any_payload(), }, + AnyPayloadProvider { + key: WeekDataV1Marker::KEY, + data: week_data.clone().wrap_into_any_payload(), + }, ], }; diff --git a/components/datetime/tests/fixtures/tests/components-exact-matches.json b/components/datetime/tests/fixtures/tests/components-exact-matches.json index 6164ce944d1..d43d69d0f02 100644 --- a/components/datetime/tests/fixtures/tests/components-exact-matches.json +++ b/components/datetime/tests/fixtures/tests/components-exact-matches.json @@ -515,7 +515,7 @@ "description": "Exact match for: yw => week' w 'of' Y", "input": { "locale": "en", - "value": "2016-04-13T08:25:07.000", + "value": "2016-04-17T08:25:07.000", "options": { "components": { "year": "numeric-week-of", @@ -525,25 +525,9 @@ }, "output": { "values": { - "en": "week 15 of 2016" - } - } - }, - { - "description": "Exact match for: yw => week' w 'of' Y with Y different from y", - "input": { - "locale": "en", - "value": "2022-01-01T08:25:07.000", - "options": { - "components": { - "year": "numeric-week-of", - "week": "numeric-week-of-year" - } - } - }, - "output": { - "values": { - "en": "week 52 of 2021" + "en": "week 16 of 2016", + "fil": "linggo 16 ng 2016", + "en-ZA": "week 17 of 2016" } } } diff --git a/components/datetime/tests/fixtures/tests/components-partial-matches.json b/components/datetime/tests/fixtures/tests/components-partial-matches.json index dc2cb53e4a7..baa1db04bb2 100644 --- a/components/datetime/tests/fixtures/tests/components-partial-matches.json +++ b/components/datetime/tests/fixtures/tests/components-partial-matches.json @@ -66,8 +66,7 @@ }, "output": { "values": { - "en": "week 01 of 2003", - "fr": "semaine 01 de 2003" + "en": "week 53 of 2002" } } } diff --git a/components/datetime/tests/fixtures/tests/components-width-differences.json b/components/datetime/tests/fixtures/tests/components-width-differences.json index 7edf7a1a6ba..88df1a37b91 100644 --- a/components/datetime/tests/fixtures/tests/components-width-differences.json +++ b/components/datetime/tests/fixtures/tests/components-width-differences.json @@ -46,9 +46,8 @@ }, "output": { "values": { - "en": "week 1 of 03", - "fil": "ika-1 linggo ng 03", - "fr": "semaine 1 de 03" + "en": "week 53 of 02", + "fil": "linggo 53 ng 02" } } }, @@ -65,9 +64,8 @@ }, "output": { "values": { - "en": "week 1 of 02", - "fil": "ika-1 linggo ng 02", - "fr": "semaine 1 de 02" + "en": "week 53 of 02", + "fil": "linggo 53 ng 02" } } }, diff --git a/components/datetime/tests/fixtures/tests/components_with_zones.json b/components/datetime/tests/fixtures/tests/components_with_zones.json index bff37c96f9d..fcec772d0ec 100644 --- a/components/datetime/tests/fixtures/tests/components_with_zones.json +++ b/components/datetime/tests/fixtures/tests/components_with_zones.json @@ -115,10 +115,10 @@ } }, { - "description": "Date time example that includes a date that has plural variants (via week-of-year)", + "description": "Date time example that includes a week-of for a locale with plural variants as well as one with non default WeekData", "input": { "locale": "en", - "value": "2016-04-13T08:25:07.000+05:00", + "value": "2016-04-17T08:25:07.000+05:00", "options": { "components": { "year": "numeric", @@ -132,7 +132,8 @@ }, "output": { "values": { - "en": "week 15 of 2016, 08:25:07 GMT+05:00" + "fil": "linggo 16 ng 2016, 08:25:07 GMT+05:00", + "en-ZA": "week 17 of 2016, 08:25:07 GMT+05:00" } } } diff --git a/provider/cldr/src/cldr_serde/mod.rs b/provider/cldr/src/cldr_serde/mod.rs index 82410d09426..c666c5d1797 100644 --- a/provider/cldr/src/cldr_serde/mod.rs +++ b/provider/cldr/src/cldr_serde/mod.rs @@ -16,3 +16,4 @@ pub mod numbering_systems; pub mod numbers; pub mod plurals; pub mod time_zone_names; +pub mod week_data; diff --git a/provider/cldr/src/cldr_serde/week_data.rs b/provider/cldr/src/cldr_serde/week_data.rs new file mode 100644 index 00000000000..331563db8d9 --- /dev/null +++ b/provider/cldr/src/cldr_serde/week_data.rs @@ -0,0 +1,134 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Serde structs representing CLDR JSON weekData.json files. +//! +//! Sample file: +//! `` + +use core::convert::TryFrom; +use serde::{Deserialize, Deserializer}; +use std::collections::BTreeMap; +use std::num::ParseIntError; +use std::str::FromStr; +use tinystr::{tinystr, TinyStr4}; + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Weekday { + Mon, + Tue, + Wed, + Thu, + Fri, + Sat, + Sun, +} + +impl From<&Weekday> for icu_calendar::types::IsoWeekday { + fn from(day: &Weekday) -> Self { + use icu_calendar::types::IsoWeekday; + match day { + Weekday::Mon => IsoWeekday::Monday, + Weekday::Tue => IsoWeekday::Tuesday, + Weekday::Wed => IsoWeekday::Wednesday, + Weekday::Thu => IsoWeekday::Thursday, + Weekday::Fri => IsoWeekday::Friday, + Weekday::Sat => IsoWeekday::Saturday, + Weekday::Sun => IsoWeekday::Sunday, + } + } +} + +/// The territory that data is keyed by. +/// +/// For example the "AD" in "weekData": { "minDays": { "AD": 4, } } +/// +/// The contained types are strings rather than [icu_locid::subtags::Region] +/// to avoid an extra parsing step of the variant in data providers. +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum Territory { + // A territory string, e.g. "AD" for Andorra. + Region(TinyStr4), + // An alternative variant for a given territory (e.g. the first day of the + // week can be sunday rather than monday GB). The string is set to the region + // with the "-alt-variant" suffix present in the json. + AltVariantRegion(TinyStr4), +} + +/// The string used to represent the default territory. +pub const DEFAULT_TERRITORY: Territory = Territory::Region(tinystr!(4, "001")); + +/// Suffix used to denote alternative week data variants for a given territory (e.g. English BC/AD v English BCE/CE). +const ALT_VARIANT_SUFFIX: &str = "-alt-variant"; + +impl<'de> Deserialize<'de> for Territory { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TerritoryVisitor; + + impl<'de> serde::de::Visitor<'de> for TerritoryVisitor { + type Value = Territory; + + fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!( + formatter, + "a valid Unicode Language Identifier or default territory literal" + ) + } + + fn visit_str(self, s: &str) -> Result + where + E: serde::de::Error, + { + if let Some(prefix) = s.strip_suffix(ALT_VARIANT_SUFFIX) { + return Ok(Territory::AltVariantRegion( + prefix + .parse::() + .map_err(serde::de::Error::custom)?, + )); + } + + Ok(Territory::Region( + s.parse::().map_err(serde::de::Error::custom)?, + )) + } + } + + deserializer.deserialize_string(TerritoryVisitor) + } +} + +/// Wrapper used to deserialize json string keys as u8s. +#[derive(Debug, Deserialize)] +#[serde(try_from = "String")] +pub struct U8(pub u8); + +impl TryFrom for U8 { + type Error = ParseIntError; + + fn try_from(s: String) -> Result { + Ok(Self(u8::from_str(&s)?)) + } +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WeekData { + pub min_days: BTreeMap, + pub first_day: BTreeMap, +} + +#[derive(Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Supplemental { + pub week_data: WeekData, +} + +#[derive(Deserialize)] +pub struct Resource { + pub supplemental: Supplemental, +} diff --git a/provider/cldr/src/lib.rs b/provider/cldr/src/lib.rs index 02d8256823b..dc30e195f8f 100644 --- a/provider/cldr/src/lib.rs +++ b/provider/cldr/src/lib.rs @@ -42,6 +42,7 @@ use transform::calendar::japanese::JapaneseErasProvider; use transform::datetime::patterns::DatePatternsProvider; use transform::datetime::skeletons::DateSkeletonPatternsProvider; use transform::datetime::symbols::DateSymbolsProvider; +use transform::datetime::week_data::WeekDataProvider; use transform::decimal::NumbersProvider; #[cfg(feature = "icu_list")] use transform::list::ListProvider; @@ -68,6 +69,7 @@ where PluralsProvider: IterableDynProvider, TimeZonesProvider: IterableDynProvider, ListProvider: IterableDynProvider, + WeekDataProvider: IterableDynProvider, { #[allow(unused_variables)] // uprops_root is only used if icu_list Ok(MultiForkByKeyProvider { @@ -81,13 +83,14 @@ where Box::new(NumbersProvider::try_from(cldr_paths)?), Box::new(PluralsProvider::try_from(cldr_paths)?), Box::new(TimeZonesProvider::try_from(cldr_paths)?), + Box::new(WeekDataProvider::try_from(cldr_paths)?), #[cfg(feature = "icu_list")] Box::new(ListProvider::try_from(cldr_paths, _uprops_root)?), ], }) } -pub const ALL_KEYS: [ResourceKey; if cfg!(feature = "icu_list") { 18 } else { 15 }] = [ +pub const ALL_KEYS: [ResourceKey; if cfg!(feature = "icu_list") { 19 } else { 16 }] = [ icu_calendar::provider::JapaneseErasV1Marker::KEY, icu_datetime::provider::calendar::DatePatternsV1Marker::KEY, icu_datetime::provider::calendar::DateSkeletonPatternsV1Marker::KEY, @@ -98,6 +101,7 @@ pub const ALL_KEYS: [ResourceKey; if cfg!(feature = "icu_list") { 18 } else { 15 icu_datetime::provider::time_zones::MetaZoneGenericNamesShortV1Marker::KEY, icu_datetime::provider::time_zones::MetaZoneSpecificNamesLongV1Marker::KEY, icu_datetime::provider::time_zones::MetaZoneSpecificNamesShortV1Marker::KEY, + icu_datetime::provider::week_data::WeekDataV1Marker::KEY, icu_decimal::provider::DecimalSymbolsV1Marker::KEY, #[cfg(feature = "icu_list")] icu_list::provider::AndListV1Marker::KEY, diff --git a/provider/cldr/src/transform/datetime/mod.rs b/provider/cldr/src/transform/datetime/mod.rs index eebb4ce8dcf..5c4ba257769 100644 --- a/provider/cldr/src/transform/datetime/mod.rs +++ b/provider/cldr/src/transform/datetime/mod.rs @@ -6,3 +6,4 @@ mod common; pub mod patterns; pub mod skeletons; pub mod symbols; +pub mod week_data; diff --git a/provider/cldr/src/transform/datetime/week_data.rs b/provider/cldr/src/transform/datetime/week_data.rs new file mode 100644 index 00000000000..bce5549a054 --- /dev/null +++ b/provider/cldr/src/transform/datetime/week_data.rs @@ -0,0 +1,199 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use crate::cldr_serde::{ + self, + week_data::{Territory, DEFAULT_TERRITORY}, +}; +use crate::error::Error; +use crate::reader::open_reader; +use crate::CldrPaths; +use icu_calendar::arithmetic::week_of::CalendarInfo; +use icu_datetime::provider::week_data::*; +use icu_provider::iter::IterableResourceProvider; +use icu_provider::prelude::*; +use std::borrow::Cow; +use std::collections::HashSet; +use std::convert::TryFrom; +use tinystr::TinyStr4; + +/// A data provider reading from CLDR JSON weekData files. +#[derive(Debug)] +pub struct WeekDataProvider { + default: CalendarInfo, + week_data: cldr_serde::week_data::WeekData, +} + +impl TryFrom<&dyn CldrPaths> for WeekDataProvider { + type Error = Error; + fn try_from(cldr_paths: &dyn CldrPaths) -> Result { + let path = cldr_paths.cldr_core()?.join("supplemental/weekData.json"); + + let resource: cldr_serde::week_data::Resource = + serde_json::from_reader(open_reader(&path)?).map_err(|e| (e, path))?; + let week_data = resource.supplemental.week_data; + + let default = CalendarInfo { + first_weekday: week_data + .first_day + .get(&DEFAULT_TERRITORY) + .ok_or_else(|| { + Error::Custom( + "Missing default entry for firstDay in weekData.json".to_string(), + None, + ) + })? + .into(), + min_week_days: week_data + .min_days + .get(&DEFAULT_TERRITORY) + .ok_or_else(|| { + Error::Custom( + "Missing default entry for minDays in weekData.json".to_string(), + None, + ) + })? + .0, + }; + + Ok(Self { default, week_data }) + } +} + +impl IterableResourceProvider for WeekDataProvider { + #[allow(clippy::needless_collect)] // https://github.com/rust-lang/rust-clippy/issues/7526 + fn supported_options(&self) -> Result>, DataError> { + let regions: HashSet> = self + .week_data + .min_days + .keys() + .chain(self.week_data.first_day.keys()) + .filter_map(|t| match t { + &DEFAULT_TERRITORY => Some(None), + Territory::Region(r) => Some(Some(*r)), + _ => None, + }) + .collect(); + Ok(Box::new(regions.into_iter().map(|r| ResourceOptions { + variant: r.map(|r| Cow::Owned(r.to_string())), + langid: None, + }))) + } +} + +impl ResourceProvider for WeekDataProvider { + fn load_resource( + &self, + req: &DataRequest, + ) -> Result, DataError> { + let metadata = DataResponseMetadata::default(); + // TODO(#1109): Set metadata.data_langid correctly. + let territory = req + .options + .variant + .as_ref() + .map(|v| -> Result { + Ok(Territory::Region( + TinyStr4::from_bytes(v.as_bytes()).map_err(|_| { + DataErrorKind::MissingVariant.with_req(WeekDataV1Marker::KEY, req) + })?, + )) + }) + .transpose()? + .unwrap_or_else(|| DEFAULT_TERRITORY.clone()); + + Ok(DataResponse { + metadata, + payload: Some(DataPayload::from_owned(WeekDataV1(CalendarInfo { + first_weekday: self + .week_data + .first_day + .get(&territory) + .map(|w| w.into()) + .unwrap_or(self.default.first_weekday), + min_week_days: self + .week_data + .min_days + .get(&territory) + .map(|c| c.0) + .unwrap_or(self.default.min_week_days), + }))), + }) + } +} + +icu_provider::impl_dyn_provider!(WeekDataProvider, [WeekDataV1Marker,], SERDE_SE); + +#[test] +fn basic_cldr_week_data() { + use icu_calendar::types::IsoWeekday; + use icu_locid_macros::langid; + + let cldr_paths = crate::cldr_paths::for_test(); + let provider = WeekDataProvider::try_from(&cldr_paths as &dyn CldrPaths).unwrap(); + + let default_week_data: DataPayload = provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: None, + langid: Some(langid!("en")), // We don't actually care about langid. + }, + metadata: Default::default(), + }) + .unwrap() + .take_payload() + .unwrap(); + assert_eq!(1, default_week_data.get().0.min_week_days); + assert_eq!(IsoWeekday::Monday, default_week_data.get().0.first_weekday); + + let fr_week_data: DataPayload = provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: Some("FR".into()), + langid: None, + }, + metadata: Default::default(), + }) + .unwrap() + .take_payload() + .unwrap(); + assert_eq!(4, fr_week_data.get().0.min_week_days); + assert_eq!(IsoWeekday::Monday, fr_week_data.get().0.first_weekday); + + let iq_week_data: DataPayload = provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: Some("IQ".into()), + langid: Some(langid!("fr-FR")), + }, + metadata: Default::default(), + }) + .unwrap() + .take_payload() + .unwrap(); + // Only first_weekday is defined for IQ, min_week_days uses the default. + assert_eq!( + default_week_data.get().0.min_week_days, + iq_week_data.get().0.min_week_days + ); + assert_eq!(IsoWeekday::Saturday, iq_week_data.get().0.first_weekday); + + let gg_week_data: DataPayload = provider + .load_resource(&DataRequest { + options: ResourceOptions { + variant: Some("GG".into()), + langid: None, + }, + metadata: Default::default(), + }) + .unwrap() + .take_payload() + .unwrap(); + assert_eq!(4, gg_week_data.get().0.min_week_days); + // Only min_week_days is defined for GG, first_weekday uses the default. + assert_eq!( + default_week_data.get().0.first_weekday, + gg_week_data.get().0.first_weekday + ); +} diff --git a/provider/testdata/Cargo.toml b/provider/testdata/Cargo.toml index 3251d880266..819ca596238 100644 --- a/provider/testdata/Cargo.toml +++ b/provider/testdata/Cargo.toml @@ -112,6 +112,7 @@ cldr_json_glob = [ "cldr-core/supplemental/numberingSystems.json", "cldr-core/supplemental/ordinals.json", "cldr-core/supplemental/plurals.json", + "cldr-core/supplemental/weekData.json", "cldr-dates-full/main/$LOCALES/ca-gregorian.json", "cldr-numbers-full/main/$LOCALES/numbers.json", "cldr-dates-full/main/$LOCALES/timeZoneNames.json", diff --git a/provider/testdata/data/cldr/cldr-core/supplemental/weekData.json b/provider/testdata/data/cldr/cldr-core/supplemental/weekData.json new file mode 100644 index 00000000000..0315f75ef3f --- /dev/null +++ b/provider/testdata/data/cldr/cldr-core/supplemental/weekData.json @@ -0,0 +1,569 @@ +{ + "supplemental": { + "version": { + "_unicodeVersion": "14.0.0", + "_cldrVersion": "40" + }, + "weekData": { + "minDays": { + "001": "1", + "AD": "4", + "AN": "4", + "AT": "4", + "AX": "4", + "BE": "4", + "BG": "4", + "CH": "4", + "CZ": "4", + "DE": "4", + "DK": "4", + "EE": "4", + "ES": "4", + "FI": "4", + "FJ": "4", + "FO": "4", + "FR": "4", + "GB": "4", + "GF": "4", + "GG": "4", + "GI": "4", + "GP": "4", + "GR": "4", + "GU": "1", + "HU": "4", + "IE": "4", + "IM": "4", + "IS": "4", + "IT": "4", + "JE": "4", + "LI": "4", + "LT": "4", + "LU": "4", + "MC": "4", + "MQ": "4", + "NL": "4", + "NO": "4", + "PL": "4", + "PT": "4", + "RE": "4", + "RU": "4", + "SE": "4", + "SJ": "4", + "SK": "4", + "SM": "4", + "UM": "1", + "US": "1", + "VA": "4", + "VI": "1" + }, + "firstDay": { + "001": "mon", + "AD": "mon", + "AE": "sat", + "AF": "sat", + "AG": "sun", + "AI": "mon", + "AL": "mon", + "AM": "mon", + "AN": "mon", + "AR": "mon", + "AS": "sun", + "AT": "mon", + "AU": "mon", + "AX": "mon", + "AZ": "mon", + "BA": "mon", + "BD": "sun", + "BE": "mon", + "BG": "mon", + "BH": "sat", + "BM": "mon", + "BN": "mon", + "BR": "sun", + "BS": "sun", + "BT": "sun", + "BW": "sun", + "BY": "mon", + "BZ": "sun", + "CA": "sun", + "CH": "mon", + "CL": "mon", + "CM": "mon", + "CN": "sun", + "CO": "sun", + "CR": "mon", + "CY": "mon", + "CZ": "mon", + "DE": "mon", + "DJ": "sat", + "DK": "mon", + "DM": "sun", + "DO": "sun", + "DZ": "sat", + "EC": "mon", + "EE": "mon", + "EG": "sat", + "ES": "mon", + "ET": "sun", + "FI": "mon", + "FJ": "mon", + "FO": "mon", + "FR": "mon", + "GB": "mon", + "GB-alt-variant": "sun", + "GE": "mon", + "GF": "mon", + "GP": "mon", + "GR": "mon", + "GT": "sun", + "GU": "sun", + "HK": "sun", + "HN": "sun", + "HR": "mon", + "HU": "mon", + "ID": "sun", + "IE": "mon", + "IL": "sun", + "IN": "sun", + "IQ": "sat", + "IR": "sat", + "IS": "mon", + "IT": "mon", + "JM": "sun", + "JO": "sat", + "JP": "sun", + "KE": "sun", + "KG": "mon", + "KH": "sun", + "KR": "sun", + "KW": "sat", + "KZ": "mon", + "LA": "sun", + "LB": "mon", + "LI": "mon", + "LK": "mon", + "LT": "mon", + "LU": "mon", + "LV": "mon", + "LY": "sat", + "MC": "mon", + "MD": "mon", + "ME": "mon", + "MH": "sun", + "MK": "mon", + "MM": "sun", + "MN": "mon", + "MO": "sun", + "MQ": "mon", + "MT": "sun", + "MV": "fri", + "MX": "sun", + "MY": "mon", + "MZ": "sun", + "NI": "sun", + "NL": "mon", + "NO": "mon", + "NP": "sun", + "NZ": "mon", + "OM": "sat", + "PA": "sun", + "PE": "sun", + "PH": "sun", + "PK": "sun", + "PL": "mon", + "PR": "sun", + "PT": "sun", + "PY": "sun", + "QA": "sat", + "RE": "mon", + "RO": "mon", + "RS": "mon", + "RU": "mon", + "SA": "sun", + "SD": "sat", + "SE": "mon", + "SG": "sun", + "SI": "mon", + "SK": "mon", + "SM": "mon", + "SV": "sun", + "SY": "sat", + "TH": "sun", + "TJ": "mon", + "TM": "mon", + "TR": "mon", + "TT": "sun", + "TW": "sun", + "UA": "mon", + "UM": "sun", + "US": "sun", + "UY": "mon", + "UZ": "mon", + "VA": "mon", + "VE": "sun", + "VI": "sun", + "VN": "mon", + "WS": "sun", + "XK": "mon", + "YE": "sun", + "ZA": "sun", + "ZW": "sun" + }, + "weekendStart": { + "001": "sat", + "AE": "fri", + "AF": "thu", + "BH": "fri", + "DZ": "fri", + "EG": "fri", + "IL": "fri", + "IN": "sun", + "IQ": "fri", + "IR": "fri", + "JO": "fri", + "KW": "fri", + "LY": "fri", + "OM": "fri", + "QA": "fri", + "SA": "fri", + "SD": "fri", + "SY": "fri", + "UG": "sun", + "YE": "fri" + }, + "weekendEnd": { + "001": "sun", + "AE": "sat", + "AF": "fri", + "BH": "sat", + "DZ": "sat", + "EG": "sat", + "IL": "sat", + "IQ": "sat", + "IR": "fri", + "JO": "sat", + "KW": "sat", + "LY": "sat", + "OM": "sat", + "QA": "sat", + "SA": "sat", + "SD": "sat", + "SY": "sat", + "YE": "sat" + }, + "weekOfPreference": { + "af": [ + "weekOfDate", + "weekOfInterval", + "weekOfMonth" + ], + "am": [ + "weekOfYear", + "weekOfMonth" + ], + "az": [ + "weekOfYear", + "weekOfMonth" + ], + "bs": [ + "weekOfYear", + "weekOfMonth" + ], + "cs": [ + "weekOfYear", + "weekOfMonth" + ], + "cy": [ + "weekOfYear", + "weekOfMonth" + ], + "da": [ + "weekOfYear", + "weekOfMonth" + ], + "el": [ + "weekOfYear", + "weekOfMonth" + ], + "et": [ + "weekOfYear", + "weekOfMonth" + ], + "hi": [ + "weekOfYear", + "weekOfMonth" + ], + "ky": [ + "weekOfYear", + "weekOfMonth" + ], + "lt": [ + "weekOfYear", + "weekOfMonth" + ], + "mk": [ + "weekOfYear", + "weekOfMonth" + ], + "sk": [ + "weekOfYear", + "weekOfMonth" + ], + "ta": [ + "weekOfYear", + "weekOfMonth" + ], + "th": [ + "weekOfYear", + "weekOfMonth" + ], + "ar": [ + "weekOfMonth" + ], + "fil": [ + "weekOfMonth" + ], + "gu": [ + "weekOfMonth" + ], + "hu": [ + "weekOfMonth" + ], + "hy": [ + "weekOfMonth" + ], + "id": [ + "weekOfMonth" + ], + "kk": [ + "weekOfMonth" + ], + "ko": [ + "weekOfMonth" + ], + "be": [ + "weekOfInterval", + "weekOfMonth" + ], + "ro": [ + "weekOfInterval", + "weekOfMonth" + ], + "ru": [ + "weekOfInterval", + "weekOfMonth" + ], + "bg": [ + "weekOfDate", + "weekOfMonth", + "weekOfInterval" + ], + "de": [ + "weekOfDate", + "weekOfMonth", + "weekOfInterval" + ], + "he": [ + "weekOfDate", + "weekOfMonth", + "weekOfInterval" + ], + "pt": [ + "weekOfDate", + "weekOfMonth", + "weekOfInterval" + ], + "ur": [ + "weekOfDate", + "weekOfMonth", + "weekOfInterval" + ], + "zh": [ + "weekOfDate", + "weekOfMonth", + "weekOfInterval" + ], + "ca": [ + "weekOfDate" + ], + "es": [ + "weekOfDate" + ], + "fr": [ + "weekOfDate" + ], + "gl": [ + "weekOfDate" + ], + "en": [ + "weekOfDate", + "weekOfMonth" + ], + "bn": [ + "weekOfDate", + "weekOfMonth" + ], + "ja": [ + "weekOfDate", + "weekOfMonth" + ], + "ka": [ + "weekOfDate", + "weekOfMonth" + ], + "eu": [ + "weekOfMonth", + "weekOfDate" + ], + "fa": [ + "weekOfMonth", + "weekOfInterval" + ], + "hr": [ + "weekOfMonth", + "weekOfInterval" + ], + "it": [ + "weekOfMonth", + "weekOfInterval" + ], + "lv": [ + "weekOfMonth", + "weekOfInterval" + ], + "pl": [ + "weekOfMonth", + "weekOfInterval" + ], + "si": [ + "weekOfMonth", + "weekOfInterval" + ], + "sr": [ + "weekOfMonth", + "weekOfInterval" + ], + "uk": [ + "weekOfMonth", + "weekOfInterval" + ], + "uz": [ + "weekOfMonth", + "weekOfInterval" + ], + "fi": [ + "weekOfYear", + "weekOfDate", + "weekOfMonth" + ], + "zh-TW": [ + "weekOfYear", + "weekOfDate", + "weekOfMonth" + ], + "is": [ + "weekOfYear", + "weekOfMonth", + "weekOfInterval" + ], + "mn": [ + "weekOfYear", + "weekOfMonth", + "weekOfInterval" + ], + "nb": [ + "weekOfYear", + "weekOfMonth", + "weekOfInterval" + ], + "no": [ + "weekOfYear", + "weekOfMonth", + "weekOfInterval" + ], + "sv": [ + "weekOfYear", + "weekOfMonth", + "weekOfInterval" + ], + "vi": [ + "weekOfYear", + "weekOfMonth", + "weekOfInterval" + ], + "km": [ + "weekOfMonth", + "weekOfYear" + ], + "mr": [ + "weekOfMonth", + "weekOfYear" + ], + "kn": [ + "weekOfMonth", + "weekOfDate", + "weekOfYear" + ], + "ml": [ + "weekOfMonth", + "weekOfDate", + "weekOfYear" + ], + "pa": [ + "weekOfMonth", + "weekOfDate", + "weekOfYear" + ], + "lo": [ + "weekOfMonth", + "weekOfInterval", + "weekOfDate", + "weekOfYear" + ], + "sq": [ + "weekOfMonth", + "weekOfInterval", + "weekOfDate", + "weekOfYear" + ], + "ms": [ + "weekOfMonth", + "weekOfYear", + "weekOfInterval", + "weekOfDate" + ], + "tr": [ + "weekOfMonth", + "weekOfYear", + "weekOfInterval", + "weekOfDate" + ], + "nl": [ + "weekOfDate", + "weekOfYear", + "weekOfMonth" + ], + "sl": [ + "weekOfInterval" + ], + "sw": [ + "weekOfMonth", + "weekOfInterval", + "weekOfYear" + ], + "te": [ + "weekOfMonth", + "weekOfInterval", + "weekOfYear" + ], + "und": [ + "weekOfYear" + ], + "zu": [ + "weekOfYear", + "weekOfInterval" + ] + } + } + } +} diff --git a/provider/testdata/data/json/datetime/week_data@1.json b/provider/testdata/data/json/datetime/week_data@1.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AD.json b/provider/testdata/data/json/datetime/week_data@1/AD.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AD.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AE.json b/provider/testdata/data/json/datetime/week_data@1/AE.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AF.json b/provider/testdata/data/json/datetime/week_data@1/AF.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AF.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AG.json b/provider/testdata/data/json/datetime/week_data@1/AG.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AG.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AI.json b/provider/testdata/data/json/datetime/week_data@1/AI.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AL.json b/provider/testdata/data/json/datetime/week_data@1/AL.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AL.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AM.json b/provider/testdata/data/json/datetime/week_data@1/AM.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AN.json b/provider/testdata/data/json/datetime/week_data@1/AN.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AR.json b/provider/testdata/data/json/datetime/week_data@1/AR.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AS.json b/provider/testdata/data/json/datetime/week_data@1/AS.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AS.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AT.json b/provider/testdata/data/json/datetime/week_data@1/AT.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AU.json b/provider/testdata/data/json/datetime/week_data@1/AU.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AU.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AX.json b/provider/testdata/data/json/datetime/week_data@1/AX.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AX.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/AZ.json b/provider/testdata/data/json/datetime/week_data@1/AZ.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/AZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BA.json b/provider/testdata/data/json/datetime/week_data@1/BA.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BD.json b/provider/testdata/data/json/datetime/week_data@1/BD.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BD.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BE.json b/provider/testdata/data/json/datetime/week_data@1/BE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BG.json b/provider/testdata/data/json/datetime/week_data@1/BG.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BG.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BH.json b/provider/testdata/data/json/datetime/week_data@1/BH.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BH.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BM.json b/provider/testdata/data/json/datetime/week_data@1/BM.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BN.json b/provider/testdata/data/json/datetime/week_data@1/BN.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BR.json b/provider/testdata/data/json/datetime/week_data@1/BR.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BS.json b/provider/testdata/data/json/datetime/week_data@1/BS.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BS.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BT.json b/provider/testdata/data/json/datetime/week_data@1/BT.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BW.json b/provider/testdata/data/json/datetime/week_data@1/BW.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BW.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BY.json b/provider/testdata/data/json/datetime/week_data@1/BY.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/BZ.json b/provider/testdata/data/json/datetime/week_data@1/BZ.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/BZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CA.json b/provider/testdata/data/json/datetime/week_data@1/CA.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CH.json b/provider/testdata/data/json/datetime/week_data@1/CH.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CH.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CL.json b/provider/testdata/data/json/datetime/week_data@1/CL.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CL.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CM.json b/provider/testdata/data/json/datetime/week_data@1/CM.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CN.json b/provider/testdata/data/json/datetime/week_data@1/CN.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CO.json b/provider/testdata/data/json/datetime/week_data@1/CO.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CR.json b/provider/testdata/data/json/datetime/week_data@1/CR.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CY.json b/provider/testdata/data/json/datetime/week_data@1/CY.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/CZ.json b/provider/testdata/data/json/datetime/week_data@1/CZ.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/CZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/DE.json b/provider/testdata/data/json/datetime/week_data@1/DE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/DE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/DJ.json b/provider/testdata/data/json/datetime/week_data@1/DJ.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/DJ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/DK.json b/provider/testdata/data/json/datetime/week_data@1/DK.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/DK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/DM.json b/provider/testdata/data/json/datetime/week_data@1/DM.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/DM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/DO.json b/provider/testdata/data/json/datetime/week_data@1/DO.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/DO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/DZ.json b/provider/testdata/data/json/datetime/week_data@1/DZ.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/DZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/EC.json b/provider/testdata/data/json/datetime/week_data@1/EC.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/EC.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/EE.json b/provider/testdata/data/json/datetime/week_data@1/EE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/EE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/EG.json b/provider/testdata/data/json/datetime/week_data@1/EG.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/EG.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/ES.json b/provider/testdata/data/json/datetime/week_data@1/ES.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/ES.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/ET.json b/provider/testdata/data/json/datetime/week_data@1/ET.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/ET.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/FI.json b/provider/testdata/data/json/datetime/week_data@1/FI.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/FI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/FJ.json b/provider/testdata/data/json/datetime/week_data@1/FJ.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/FJ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/FO.json b/provider/testdata/data/json/datetime/week_data@1/FO.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/FO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/FR.json b/provider/testdata/data/json/datetime/week_data@1/FR.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/FR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GB.json b/provider/testdata/data/json/datetime/week_data@1/GB.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GB.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GE.json b/provider/testdata/data/json/datetime/week_data@1/GE.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GF.json b/provider/testdata/data/json/datetime/week_data@1/GF.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GF.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GG.json b/provider/testdata/data/json/datetime/week_data@1/GG.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GG.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GI.json b/provider/testdata/data/json/datetime/week_data@1/GI.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GP.json b/provider/testdata/data/json/datetime/week_data@1/GP.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GP.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GR.json b/provider/testdata/data/json/datetime/week_data@1/GR.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GT.json b/provider/testdata/data/json/datetime/week_data@1/GT.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/GU.json b/provider/testdata/data/json/datetime/week_data@1/GU.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/GU.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/HK.json b/provider/testdata/data/json/datetime/week_data@1/HK.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/HK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/HN.json b/provider/testdata/data/json/datetime/week_data@1/HN.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/HN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/HR.json b/provider/testdata/data/json/datetime/week_data@1/HR.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/HR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/HU.json b/provider/testdata/data/json/datetime/week_data@1/HU.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/HU.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/ID.json b/provider/testdata/data/json/datetime/week_data@1/ID.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/ID.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IE.json b/provider/testdata/data/json/datetime/week_data@1/IE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IL.json b/provider/testdata/data/json/datetime/week_data@1/IL.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IL.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IM.json b/provider/testdata/data/json/datetime/week_data@1/IM.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IN.json b/provider/testdata/data/json/datetime/week_data@1/IN.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IQ.json b/provider/testdata/data/json/datetime/week_data@1/IQ.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IQ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IR.json b/provider/testdata/data/json/datetime/week_data@1/IR.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IS.json b/provider/testdata/data/json/datetime/week_data@1/IS.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IS.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/IT.json b/provider/testdata/data/json/datetime/week_data@1/IT.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/IT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/JE.json b/provider/testdata/data/json/datetime/week_data@1/JE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/JE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/JM.json b/provider/testdata/data/json/datetime/week_data@1/JM.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/JM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/JO.json b/provider/testdata/data/json/datetime/week_data@1/JO.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/JO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/JP.json b/provider/testdata/data/json/datetime/week_data@1/JP.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/JP.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/KE.json b/provider/testdata/data/json/datetime/week_data@1/KE.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/KE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/KG.json b/provider/testdata/data/json/datetime/week_data@1/KG.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/KG.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/KH.json b/provider/testdata/data/json/datetime/week_data@1/KH.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/KH.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/KR.json b/provider/testdata/data/json/datetime/week_data@1/KR.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/KR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/KW.json b/provider/testdata/data/json/datetime/week_data@1/KW.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/KW.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/KZ.json b/provider/testdata/data/json/datetime/week_data@1/KZ.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/KZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LA.json b/provider/testdata/data/json/datetime/week_data@1/LA.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LB.json b/provider/testdata/data/json/datetime/week_data@1/LB.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LB.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LI.json b/provider/testdata/data/json/datetime/week_data@1/LI.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LK.json b/provider/testdata/data/json/datetime/week_data@1/LK.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LT.json b/provider/testdata/data/json/datetime/week_data@1/LT.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LU.json b/provider/testdata/data/json/datetime/week_data@1/LU.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LU.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LV.json b/provider/testdata/data/json/datetime/week_data@1/LV.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LV.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/LY.json b/provider/testdata/data/json/datetime/week_data@1/LY.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/LY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MC.json b/provider/testdata/data/json/datetime/week_data@1/MC.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MC.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MD.json b/provider/testdata/data/json/datetime/week_data@1/MD.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MD.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/ME.json b/provider/testdata/data/json/datetime/week_data@1/ME.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/ME.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MH.json b/provider/testdata/data/json/datetime/week_data@1/MH.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MH.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MK.json b/provider/testdata/data/json/datetime/week_data@1/MK.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MM.json b/provider/testdata/data/json/datetime/week_data@1/MM.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MN.json b/provider/testdata/data/json/datetime/week_data@1/MN.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MO.json b/provider/testdata/data/json/datetime/week_data@1/MO.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MQ.json b/provider/testdata/data/json/datetime/week_data@1/MQ.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MQ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MT.json b/provider/testdata/data/json/datetime/week_data@1/MT.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MV.json b/provider/testdata/data/json/datetime/week_data@1/MV.json new file mode 100644 index 00000000000..a2a276c4be0 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MV.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Friday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MX.json b/provider/testdata/data/json/datetime/week_data@1/MX.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MX.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MY.json b/provider/testdata/data/json/datetime/week_data@1/MY.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/MZ.json b/provider/testdata/data/json/datetime/week_data@1/MZ.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/MZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/NI.json b/provider/testdata/data/json/datetime/week_data@1/NI.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/NI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/NL.json b/provider/testdata/data/json/datetime/week_data@1/NL.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/NL.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/NO.json b/provider/testdata/data/json/datetime/week_data@1/NO.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/NO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/NP.json b/provider/testdata/data/json/datetime/week_data@1/NP.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/NP.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/NZ.json b/provider/testdata/data/json/datetime/week_data@1/NZ.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/NZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/OM.json b/provider/testdata/data/json/datetime/week_data@1/OM.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/OM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PA.json b/provider/testdata/data/json/datetime/week_data@1/PA.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PE.json b/provider/testdata/data/json/datetime/week_data@1/PE.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PH.json b/provider/testdata/data/json/datetime/week_data@1/PH.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PH.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PK.json b/provider/testdata/data/json/datetime/week_data@1/PK.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PL.json b/provider/testdata/data/json/datetime/week_data@1/PL.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PL.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PR.json b/provider/testdata/data/json/datetime/week_data@1/PR.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PT.json b/provider/testdata/data/json/datetime/week_data@1/PT.json new file mode 100644 index 00000000000..6aa991d45d5 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/PY.json b/provider/testdata/data/json/datetime/week_data@1/PY.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/PY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/QA.json b/provider/testdata/data/json/datetime/week_data@1/QA.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/QA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/RE.json b/provider/testdata/data/json/datetime/week_data@1/RE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/RE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/RO.json b/provider/testdata/data/json/datetime/week_data@1/RO.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/RO.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/RS.json b/provider/testdata/data/json/datetime/week_data@1/RS.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/RS.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/RU.json b/provider/testdata/data/json/datetime/week_data@1/RU.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/RU.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SA.json b/provider/testdata/data/json/datetime/week_data@1/SA.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SD.json b/provider/testdata/data/json/datetime/week_data@1/SD.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SD.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SE.json b/provider/testdata/data/json/datetime/week_data@1/SE.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SG.json b/provider/testdata/data/json/datetime/week_data@1/SG.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SG.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SI.json b/provider/testdata/data/json/datetime/week_data@1/SI.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SJ.json b/provider/testdata/data/json/datetime/week_data@1/SJ.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SJ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SK.json b/provider/testdata/data/json/datetime/week_data@1/SK.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SM.json b/provider/testdata/data/json/datetime/week_data@1/SM.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SV.json b/provider/testdata/data/json/datetime/week_data@1/SV.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SV.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/SY.json b/provider/testdata/data/json/datetime/week_data@1/SY.json new file mode 100644 index 00000000000..dccd3c86c2c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/SY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Saturday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/TH.json b/provider/testdata/data/json/datetime/week_data@1/TH.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/TH.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/TJ.json b/provider/testdata/data/json/datetime/week_data@1/TJ.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/TJ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/TM.json b/provider/testdata/data/json/datetime/week_data@1/TM.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/TM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/TR.json b/provider/testdata/data/json/datetime/week_data@1/TR.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/TR.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/TT.json b/provider/testdata/data/json/datetime/week_data@1/TT.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/TT.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/TW.json b/provider/testdata/data/json/datetime/week_data@1/TW.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/TW.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/UA.json b/provider/testdata/data/json/datetime/week_data@1/UA.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/UA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/UM.json b/provider/testdata/data/json/datetime/week_data@1/UM.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/UM.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/US.json b/provider/testdata/data/json/datetime/week_data@1/US.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/US.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/UY.json b/provider/testdata/data/json/datetime/week_data@1/UY.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/UY.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/UZ.json b/provider/testdata/data/json/datetime/week_data@1/UZ.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/UZ.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/VA.json b/provider/testdata/data/json/datetime/week_data@1/VA.json new file mode 100644 index 00000000000..08799742804 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/VA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 4 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/VE.json b/provider/testdata/data/json/datetime/week_data@1/VE.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/VE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/VI.json b/provider/testdata/data/json/datetime/week_data@1/VI.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/VI.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/VN.json b/provider/testdata/data/json/datetime/week_data@1/VN.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/VN.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/WS.json b/provider/testdata/data/json/datetime/week_data@1/WS.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/WS.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/XK.json b/provider/testdata/data/json/datetime/week_data@1/XK.json new file mode 100644 index 00000000000..6ab43b9468c --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/XK.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Monday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/YE.json b/provider/testdata/data/json/datetime/week_data@1/YE.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/YE.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/ZA.json b/provider/testdata/data/json/datetime/week_data@1/ZA.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/ZA.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/json/datetime/week_data@1/ZW.json b/provider/testdata/data/json/datetime/week_data@1/ZW.json new file mode 100644 index 00000000000..5dd638b4f55 --- /dev/null +++ b/provider/testdata/data/json/datetime/week_data@1/ZW.json @@ -0,0 +1,4 @@ +{ + "first_weekday": "Sunday", + "min_week_days": 1 +} diff --git a/provider/testdata/data/testdata.postcard b/provider/testdata/data/testdata.postcard index 5854bd0de414feba3d999b73532448729c2e7ed4..4f7bc9140b63bf1df3c527306819f1c2cea33758 100644 GIT binary patch delta 7535 zcmb{033LsuRFv$Y0m{W@p(gC&~`q5k+E zENbH~*mn-+aRC?cB`)DBT*kj}#Xs!_OIYJ;gx67t8~7IA;U;e3XDhV7>DVY0Y7G97G`4(=3*Y^V*wWWcP!M^Zu&OiGQ5N3co!@19#&!% zR$~p;Vx7Nop)RcHM#4?lj4jxTQf$L^lwk*U;zN}C2Q4zzE_pwwzQ6t<;}Zr&5ee{D z95On5T?o741$0AqhT&!8VL0+J0wXaB zqZRRqk6JcYq1_1{MLeq zFn?8Yc*wK6+1`VF_yh-V2#0YL$8Z8CaT;gwgWSH*?;Z^(_TL04eme#MdK2?R= z_z8C)JfRBo2!z(tO$b4CgrX)?SP+R?sDpZ_j|OOnMtD@mWAzxp6L<<*2X2OEey2Hc zD?E>Oupu5!q{52~WT68(p$mGVKL%nDhW?*?|Lws4-am{A@{o^_&_)$)L>Z3)OvEdA z6~%v+R>_~vd_S)?TxsKxHqK}R$zGhmB~;=Un0ekUh{h9W0S7XmjUL*lp!Ia$c#^4@ zjkmB0T94LxsMh<=;VQI_By<=PR6K-cXpK0uM@RI*OBjnH%)vWYkDWMx&u|gf0=WOT z2~2t(6g-S3X#G2Fh}*%2SU8Y?Bsh_Z_V6J6|Bd^fNuf^Yf^Nt`9}L7G48w4Yz$o}I z7Lzaq(@=sLe}z_=R&XZfVF4Cl36^6O)?foRVGByJ9XqfG2T_3|IQCzhVE-9>j`O&P zEAU+-sl+Y(fFJQQeu2(FA4d&5fG}A8UcSG(!auApk}psf52AsA``?h@F+7c?XpWX> zh3C;0R>UI}?cqWC-@*3>m1J_f6S|-qa?l3@F$lvj93wCaT76?N2~#i)C75yFO#aWq z0xW`W3CVJ-!WwMACTu||wqpnO;2#-dNa2md^NNz%BK}`H13Xh^0TEhXiiTmG`pf6s=I84I=EXPKa z;~-ArOI(MTnQWjo8ll-=#{K{6h5xwhGn`mUv_c!SLmZOegxg1wh74q(13DoGebFBS zG5AjyN}k~ufzcR)LcEIC@H(c$k6D-l-#n5fco*+s71sU_>)GCfE!c)K?8e8~kHh#B z$MG3X;S4U~YkY%iu*O>L);O!fnqW<~I;|;Ix7FvddaY^JOl!8yYKyhmZ4O(!&1p-q zxosYs*Op<+vSr6uW8!0yW1KN5F{v@`n5>xWSbJ<@Y*MTwSzUHlyer9->~g!juB`S}x80rU_PEnLR!^+Q?s0e$Jc*tp zkJFRx$@0c~6TJ^Py>749n~`QsbEbLHveL5Ct?Bmkg!GgQPi9ha{QL>|sZJi-( zq{%ShqaM)#C53gfeQ})_#gK?(q`(C?yhukTve6Np(G}g0gP!PxKIn%5$i-j`#W3U{ zA0sguV=xXAI?-(l2_|7OicpNHcpYzG24-S5=3+h;ViA^LDVAY5R$wJoV=dNW12$qa zwqhH~uoLB-=(f8F_Fx}A!2uk?VI0LVoWMz(##wxU^SFphxQr{fihtueZs0rILKSY~ zC)|Oyx>KO{kpvEJ<$t&&<_KUi@_L*VaP*1#$ztNL7Ohz z|EXQLl&E-tU%_ttZgl60v>#WJUN^% zghQ|K+6UdIGWgBmBvAY#KM7ck3S8;Mvgukcos8_QlUw)^mOeUZisopAcCaH6sffw#;f+SPDUe`wcaAua{Z?2MzyF^>=hKf_FlJYjiSgy-u=u`Lmui+RHn2^3^V#blj(tHV1T4e3%nBrjw^m z>EyZ3`7-BqGKlrtnJYR;xTcdgzSYU)@9`tYSkK)GP-MSRk;63~kiqw3Z*KkiO;(k_SYI>Wcf7< zmd$#3%|~KjEj9`l&}XY&zCkW)vr`zfjsIxEI;~lmUW)eXWggmo$;siyLk4++`TX&9 z26?Gwpv;I1l-2oxvTtRe9J>%Gmm`DZb!U)#Ixa{aDi4xuL$DmT2aC5bSl-ynL~}z8(Z>>QjYz&gdpZ`k(gX$l#2_EauWxc!+n7tU|MRF zAt=ItEk?PHA7I*Q6n&{t>Y{V0(I@fSjI!y5QO+7n@)as0O`xs z%OqD}sBMxdD8os72SXi`SnxR7Aq_PiG|Ap*lbpqERBJ%Jc(#GhBu;`HjKk|#j1~9> zzUC&Gig$1uLtC2UHO$9$oWP>CCi%o_lAEY*Gs!}`NovNMB(|eTdSDnPVkS=Jn#5aR zlAg$e-$$|um!T^(Ni7_jWRk*HO|lf*a0r(nMJ9>F)5t_F#-hU#lN6y8H_-GglejSi z)3E`^QH9z|P0|{j;nOT6*@5#2c-tfmQGF+kU<}?ws}H#%ShoPkC{JxL zOB$2PUQ8;-l$vGn4zp}3H_O3~XmGDtdLJ~)=nAu(XL32KX^6O{hDgt!L*%sq)x>wg zS4{@ns!NX*)n$XFhLn$~AqijCkk)CT5U}xsmkgU>T#)JYp+TNH`^Xnu6tE!lCDZ_hAR3jReVopa{?VWla8wVs}qfOp|P&2 zjC(q~|GRJqb$m4*XV*_TWCK{Pl-WxP=3 zqnA{O5rF~&W={4mEa6ybf;s}n96$i-M}MpSyZunwzQMajFVQL-23P~85`~gMt9)VL%{)5DX(sFe3!j ZP#rZ8iU&{=VNekc3nD%UEQst{^>aoyh?+T^Ke1#eGr%Xz~yR+nwD6imAN5i1S%@#LbxE33oaR@nYer1QE+KQ zy(wdgOHzoTmZoSfnQ5BKyiyxeGbeMVCe1btQ|EK%kC}PRS~I2LqYF~d)&IawkGpbDs;PJaY5wS*5uW(PRF_~WR$~p; zVjW(_dKBXoyowTRKq)r*SI+a)^xruUVHccqR4p)qqarH!{3d?HE!@T(|G6=)k^)C@ zGb7o5E63F&cqmgb%zwDp8Es7WpBU?MKak5Ob1)Zq$j5%Xg9CUM2XP4R;c&sGS2`5z z4XNYb_o}m>ubIi@pgCHgC0e01;?M^1Xp2YC4v!)MPaqAw&>MZw7wPDS42;AmJcrSk zjWaQU^3Oj7H!i080vDCwL>R(h!;6}zgS*iH_aX*?g%2!nU?JlWk9PkZ-(MOg&_N;s zQ4xrUKqLgB;Bj!kr*HvRaT}qmNOjagLj-~&u;?iWEc8%}!BkT| zEugX->rjSr9Kb1jhHLl{p+SG;q8^5DRD~N6@W6|jsD)_M`?q}m{D%58iotz|MN>3K z9O99HBy>PBIwJ+CNJj=TG4Ma}{hJ#G^WAWaz%v+$98APyOvfzbVlMJAAB$0l6 zzQXsoiCZuoQZOpP2@92Bqb6!08uflI-_LEp{q+%p`w)w!XpT6lupWV0KdUG{1Fuh z4(44)G#cSyv_og4V+3+A4fEm0T5QC2yp0n$kKg0FVAfwDk_$F!qaj+LJ-VSUvM>@; zFc(X(3a?=o4&oFp;!E5>5NA?2Y9kh{kce)7%lEez|HpbdV-1Jzd5WpX$8r>73-;oD ze2CxS3Vwhylr0wZ(FAcwLJ#!AP>g~P^RN_aun})!ACBM@E`_rHe@o>yLOH(OsEzy4 z0*|39GB5%;n28rqh?lVmJ8=YOaT#CZ_D{n4|Fj!_x%=cIkWmRPA4M3d!vimBqb}}7 z1Kf)kG(`)vLLA!u1nsyd2_4W0UC;x)&ThMkBOM_ccyYZ3%SU{ zJS>7A%kUD4um$kcS+^KsbWNgV_VnDT^5z!fQN~>=HAv8SY`cs$Pm}@8AM%LcY#n3hG&<%O`VF2Y{cgU{&?5_dhPqKXvzQM3hH9ZbE-W)Nd4-`GMTS0K zYiLKYp`;Clj=yFoeT$*`rh+`C&et^6yN;&m6sE5*H3?Ty^CeRquoD?8O`XBV*uBcsxFS=N@gi2> zWn4zf)ux7HHA=7_w-CODLC_SfP!AZ^SD@+tDUAnl$Lq(t(k zDX#}<)R7<+UJBBZ+d&#%%b|=m4xQ`n(7~||)!-=Fr&J9jfw%L+cU0)uHHZ4&`qnDY#B$(3=ijK(Fl%9Ycp54wa%A$Ky7%-s#Xf z#O>lYD)8f54y7G&XegYY@^IK$FIfEt1gmIsupX%vq9>C=G+}&*7MF%-6(`naPbKy1 zQb{YPRnnLHDyhED5vroZP}QClsxjL`*=n77tgTb2&pDNiDOiYAID~qmoq7nf#yYhC zew5(^E+RGGsf{b0+Kpvvoq82-;{(L6b1DrjcQ~~JZ^QQi#nE!7E~6ovd-YvT&A8@N zvBRZJDEGK@1SfGGmvI9zQ7*N{8kBln+KOZ7Q^Tb^ti@Y6h70%(u9_}ICA9W!!;>{Wum~&=1+j!8Rm6>{4Hh#(uPI=~6EY!(6P!)9lqt+qtwGAL6M* zm(I3#DLmb!CTNH57>KpcawycE=~7c9U;t)dGY;cZEN9>C#=biebFdtn@g6SX2h_`F zHqaRj*oV`Qi=DWMyVklCk4#KO5%%Gdk0OLkyCIVC6!NhF@8b$S+`}N~wAZB(2;Rqx zVBCHl`V50&FtSnOE=ygSTgt+fOiOq0`9Mo2vn&-qWoh1MOL1c?eUW3SaGb?IB@-+? zKgrV8DVB1kTIxOBl54i5gL5p+&bO2_pUxIpYO~nV_$8JWy=bYV&{CfwOVdg$4Jl>7 z*DO7_$xOEccKwCn%_9<=n(QA-_EVq62Sim(~wIF3uGe2-U+k%BBt#`xA=jp^!D0ZQ;8zD3o?y}BPs$iWLJ z!`>$-F5(+B?B-Pl3UCPJ-MzYsxjnoJ?deq}CZiB1a23y_di5oqe!{Cf6r;@azwnYP zYRl2ajWTA$&dZIRXTU@d90*1TDj^h3xL_d+l@X3AsETT+4mWH>AQGN!vGby)-}n Date: Wed, 23 Feb 2022 18:05:41 -0800 Subject: [PATCH 2/5] Remove duplicate implementation in LineBreakType (#1630) * Implement get_linebreak_property() in LineBreakIterator * Implement is_break_by_normal() in LineBreakIterator --- experimental/segmenter/src/line.rs | 56 +++++++----------------------- 1 file changed, 13 insertions(+), 43 deletions(-) diff --git a/experimental/segmenter/src/line.rs b/experimental/segmenter/src/line.rs index 63e5ffd92f7..fe57a255f26 100644 --- a/experimental/segmenter/src/line.rs +++ b/experimental/segmenter/src/line.rs @@ -233,7 +233,7 @@ fn get_linebreak_property_with_rule( #[inline] fn is_break_utf32_by_normal(codepoint: u32, ja_zh: bool) -> bool { - match codepoint as u32 { + match codepoint { 0x301C => ja_zh, 0x30A0 => ja_zh, _ => false, @@ -382,15 +382,11 @@ pub trait LineBreakType<'l, 's> { fn use_complex_breaking(iterator: &LineBreakIterator<'l, 's, Self>, c: Self::CharType) -> bool; - fn get_linebreak_property(iterator: &LineBreakIterator<'l, 's, Self>) -> u8; - fn get_linebreak_property_with_rule( iterator: &LineBreakIterator<'l, 's, Self>, c: Self::CharType, ) -> u8; - fn is_break_by_normal(iterator: &LineBreakIterator<'l, 's, Self>) -> bool; - fn get_line_break_by_platform_fallback( iterator: &LineBreakIterator<'l, 's, Self>, input: &[u16], @@ -444,14 +440,14 @@ impl<'l, 's, Y: LineBreakType<'l, 's>> Iterator for LineBreakIterator<'l, 's, Y> } loop { - let mut left_prop = Y::get_linebreak_property(self); + let mut left_prop = self.get_linebreak_property(); let left_codepoint = self.current_pos_data; self.current_pos_data = self.iter.next(); if self.current_pos_data.is_none() { // EOF return Some(self.len); } - let right_prop = Y::get_linebreak_property(self); + let right_prop = self.get_linebreak_property(); // CSS word-break property handling match self.options.word_break_rule { @@ -474,7 +470,7 @@ impl<'l, 's, Y: LineBreakType<'l, 's>> Iterator for LineBreakIterator<'l, 's, Y> // CSS line-break property handling match self.options.line_break_rule { LineBreakRule::Normal => { - if Y::is_break_by_normal(self) { + if self.is_break_by_normal() { return Some(self.current_pos_data.unwrap().0); } } @@ -534,7 +530,7 @@ impl<'l, 's, Y: LineBreakType<'l, 's>> Iterator for LineBreakIterator<'l, 's, Y> return Some(self.len); } - let prop = Y::get_linebreak_property(self); + let prop = self.get_linebreak_property(); break_state = get_break_state_from_table(&self.data.rule_table, break_state as u8, prop); if break_state < 0 { @@ -574,6 +570,14 @@ impl<'l, 's, Y: LineBreakType<'l, 's>> LineBreakIterator<'l, 's, Y> { false } + fn get_linebreak_property(&self) -> u8 { + Y::get_linebreak_property_with_rule(self, self.current_pos_data.unwrap().1) + } + + fn is_break_by_normal(&self) -> bool { + is_break_utf32_by_normal(self.current_pos_data.unwrap().1.into(), self.options.ja_zh) + } + // UAX14 doesn't define line break rules for some languages such as Thai. // These languages uses dictionary-based breaker, so we use OS's line breaker instead. fn handle_complex_language(&mut self, left_codepoint: Y::CharType) -> Option { @@ -617,10 +621,6 @@ impl<'l, 's> LineBreakType<'l, 's> for char { type IterAttr = CharIndices<'s>; type CharType = char; - fn get_linebreak_property(iterator: &LineBreakIterator) -> u8 { - Self::get_linebreak_property_with_rule(iterator, iterator.current_pos_data.unwrap().1) - } - fn get_linebreak_property_with_rule(iterator: &LineBreakIterator, c: char) -> u8 { get_linebreak_property_with_rule( &iterator.data.property_table, @@ -630,13 +630,6 @@ impl<'l, 's> LineBreakType<'l, 's> for char { ) } - fn is_break_by_normal(iterator: &LineBreakIterator) -> bool { - is_break_utf32_by_normal( - iterator.current_pos_data.unwrap().1 as u32, - iterator.options.ja_zh, - ) - } - #[inline] fn use_complex_breaking(iterator: &LineBreakIterator, c: char) -> bool { use_complex_breaking_utf32(&iterator.data.property_table, c as u32) @@ -681,23 +674,11 @@ impl<'l, 's> LineBreakType<'l, 's> for Latin1Char { type IterAttr = Latin1Indices<'s>; type CharType = u8; // TODO: Latin1Char - fn get_linebreak_property(iterator: &LineBreakIterator) -> u8 { - // No CJ on Latin1 - Self::get_linebreak_property_with_rule(iterator, iterator.current_pos_data.unwrap().1) - } - fn get_linebreak_property_with_rule(iterator: &LineBreakIterator, c: u8) -> u8 { // No CJ on Latin1 get_linebreak_property_latin1(&iterator.data.property_table, c) } - fn is_break_by_normal(iterator: &LineBreakIterator) -> bool { - is_break_utf32_by_normal( - iterator.current_pos_data.unwrap().1 as u32, - iterator.options.ja_zh, - ) - } - #[inline] fn use_complex_breaking(_iterator: &LineBreakIterator, _c: u8) -> bool { false @@ -718,10 +699,6 @@ impl<'l, 's> LineBreakType<'l, 's> for Utf16Char { type IterAttr = Utf16Indices<'s>; type CharType = u32; // TODO: Utf16Char - fn get_linebreak_property(iterator: &LineBreakIterator) -> u8 { - Self::get_linebreak_property_with_rule(iterator, iterator.current_pos_data.unwrap().1) - } - fn get_linebreak_property_with_rule(iterator: &LineBreakIterator, c: u32) -> u8 { get_linebreak_property_utf32_with_rule( &iterator.data.property_table, @@ -731,13 +708,6 @@ impl<'l, 's> LineBreakType<'l, 's> for Utf16Char { ) } - fn is_break_by_normal(iterator: &LineBreakIterator) -> bool { - is_break_utf32_by_normal( - iterator.current_pos_data.unwrap().1 as u32, - iterator.options.ja_zh, - ) - } - #[inline] fn use_complex_breaking(iterator: &LineBreakIterator, c: u32) -> bool { use_complex_breaking_utf32(&iterator.data.property_table, c) From 938ed36605d6dc6861d1ff60fe409e35e2761a00 Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Wed, 23 Feb 2022 19:55:37 -0800 Subject: [PATCH 3/5] Wire DataProvider into UAX29 segmenters (#1627) * Wire DataProvider into UAX29 segmenters The UAX29 segmenters and iterators share the same data structure. This PR moves all the data required to initialize `RuleBreakIterator` into `RuleBreakDataV1`, and implements `RuleBreakDataProvider` to load the generated data under `OUT_DIR`. In the future, `RuleBreakDataProvider` can be replaced by any formal DataProvider loading data from blob or elsewhere. * Change RuleBreakDataV1::property_count from usize to u8 `usize` has different sizes on 32 bit and 64 bit system. Use `u8` so that it has consistent size across all platforms. Generate PROPERTY_COUNT as `u8` directly in `build.rs`. * Change other fields in RuleBreakDataV1 from usize to u8 * Change PROPERTY_TABLE to be a 2d array instead of an array of references Also, change "pub const PROPERTY_TABLE" to "pub static PROPERTY_TABLE" to fix this clippy warning: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays --- experimental/segmenter/README.md | 18 ++- experimental/segmenter/build.rs | 14 +- experimental/segmenter/src/grapheme.rs | 44 ++---- experimental/segmenter/src/lib.rs | 21 ++- experimental/segmenter/src/provider.rs | 157 ++++++++++++++++++- experimental/segmenter/src/rule_segmenter.rs | 26 ++- experimental/segmenter/src/sentence.rs | 44 ++---- experimental/segmenter/src/word.rs | 48 +++--- experimental/segmenter/tests/complex_word.rs | 7 +- experimental/segmenter/tests/spec_test.rs | 10 +- 10 files changed, 263 insertions(+), 126 deletions(-) diff --git a/experimental/segmenter/README.md b/experimental/segmenter/README.md index a61feefcc17..c50faeba930 100644 --- a/experimental/segmenter/README.md +++ b/experimental/segmenter/README.md @@ -62,7 +62,8 @@ Segment a string: ```rust use icu_segmenter::GraphemeClusterBreakSegmenter; -let segmenter = GraphemeClusterBreakSegmenter::try_new() +let provider = icu_segmenter::RuleBreakDataProvider; +let segmenter = GraphemeClusterBreakSegmenter::try_new(&provider) .expect("Data exists"); let breakpoints: Vec = segmenter.segment_str("Hello 🗺").collect(); @@ -74,7 +75,8 @@ Segment a Latin1 byte string: ```rust use icu_segmenter::GraphemeClusterBreakSegmenter; -let segmenter = GraphemeClusterBreakSegmenter::try_new() +let provider = icu_segmenter::RuleBreakDataProvider; +let segmenter = GraphemeClusterBreakSegmenter::try_new(&provider) .expect("Data exists"); let breakpoints: Vec = segmenter.segment_latin1(b"Hello World").collect(); @@ -87,7 +89,8 @@ Segment a string: ```rust use icu_segmenter::WordBreakSegmenter; -let segmenter = WordBreakSegmenter::try_new() +let provider = icu_segmenter::RuleBreakDataProvider; +let segmenter = WordBreakSegmenter::try_new(&provider) .expect("Data exists"); let breakpoints: Vec = segmenter.segment_str("Hello World").collect(); @@ -98,7 +101,8 @@ Segment a Latin1 byte string: ```rust use icu_segmenter::WordBreakSegmenter; -let segmenter = WordBreakSegmenter::try_new() +let provider = icu_segmenter::RuleBreakDataProvider; +let segmenter = WordBreakSegmenter::try_new(&provider) .expect("Data exists"); let breakpoints: Vec = segmenter.segment_latin1(b"Hello World").collect(); @@ -111,7 +115,8 @@ Segment a string: ```rust use icu_segmenter::SentenceBreakSegmenter; -let segmenter = SentenceBreakSegmenter::try_new() +let provider = icu_segmenter::RuleBreakDataProvider; +let segmenter = SentenceBreakSegmenter::try_new(&provider) .expect("Data exists"); let breakpoints: Vec = segmenter.segment_str("Hello World").collect(); @@ -122,7 +127,8 @@ Segment a Latin1 byte string: ```rust use icu_segmenter::SentenceBreakSegmenter; -let segmenter = SentenceBreakSegmenter::try_new() +let provider = icu_segmenter::RuleBreakDataProvider; +let segmenter = SentenceBreakSegmenter::try_new(&provider) .expect("Data exists"); let breakpoints: Vec = segmenter.segment_latin1(b"Hello World").collect(); diff --git a/experimental/segmenter/build.rs b/experimental/segmenter/build.rs index 9209cb0f3d3..cff010245c0 100644 --- a/experimental/segmenter/build.rs +++ b/experimental/segmenter/build.rs @@ -647,12 +647,12 @@ fn generate_rule_segmenter_table(file_name: &str, toml_data: &[u8], provider: &F } else { writeln!( out, - "pub const PROPERTY_TABLE: [&[u8; 1024]; {}] = [", + "pub static PROPERTY_TABLE: [[u8; 1024]; {}] = [", CODEPOINT_TABLE_LEN / 1024 ) .ok(); for i in codepoint_table.iter() { - writeln!(out, " &{},", i).ok(); + writeln!(out, " {},", i).ok(); } writeln!(out, "];").ok(); } @@ -679,7 +679,7 @@ fn generate_rule_segmenter_table(file_name: &str, toml_data: &[u8], provider: &F writeln!( out, - "pub const PROPERTY_COUNT: usize = {};", + "pub const PROPERTY_COUNT: u8 = {};", properties_names.len() ) .ok(); @@ -692,21 +692,21 @@ fn generate_rule_segmenter_table(file_name: &str, toml_data: &[u8], provider: &F writeln!( out, - "pub const PROP_SOT: usize = {};", + "pub const PROP_SOT: u8 = {};", properties_names.len() - 2 ) .ok(); writeln!( out, - "pub const PROP_EOT: usize = {};", + "pub const PROP_EOT: u8 = {};", properties_names.len() - 1 ) .ok(); if let Some(sa_index) = get_index_from_name(&properties_names, "SA") { - writeln!(out, "pub const PROP_COMPLEX: usize = {};", sa_index,).ok(); + writeln!(out, "pub const PROP_COMPLEX: u8 = {};", sa_index,).ok(); } else { // complex language isn't handled. - writeln!(out, "pub const PROP_COMPLEX: usize = 127;").ok(); + writeln!(out, "pub const PROP_COMPLEX: u8 = 127;").ok(); } for (i, p) in properties_names.iter().enumerate() { diff --git a/experimental/segmenter/src/grapheme.rs b/experimental/segmenter/src/grapheme.rs index a3c1c05e0e1..91298eb427b 100644 --- a/experimental/segmenter/src/grapheme.rs +++ b/experimental/segmenter/src/grapheme.rs @@ -4,13 +4,12 @@ use alloc::vec::Vec; use core::str::CharIndices; -use icu_provider::DataError; +use icu_provider::prelude::*; use crate::indices::{Latin1Indices, Utf16Indices}; +use crate::provider::*; use crate::rule_segmenter::*; -include!(concat!(env!("OUT_DIR"), "/generated_grapheme_table.rs")); - /// Grapheme cluster break iterator for an `str` (a UTF-8 string). pub type GraphemeClusterBreakIterator<'l, 's> = RuleBreakIterator<'l, 's, GraphemeClusterBreakType>; @@ -26,12 +25,19 @@ pub type GraphemeClusterBreakIteratorUtf16<'l, 's> = /// different string encodings. Please see the [module-level documentation] for its usages. /// /// [module-level documentation]: index.html -pub struct GraphemeClusterBreakSegmenter; +pub struct GraphemeClusterBreakSegmenter { + payload: DataPayload, +} impl GraphemeClusterBreakSegmenter { - pub fn try_new() -> Result { - // Note: This will be able to return an Error once DataProvider is added - Ok(Self) + pub fn try_new(provider: &D) -> Result + where + D: ResourceProvider + ?Sized, + { + let payload = provider + .load_resource(&DataRequest::default())? + .take_payload()?; + Ok(Self { payload }) } /// Create a grapheme cluster break iterator for an `str` (a UTF-8 string). @@ -41,13 +47,7 @@ impl GraphemeClusterBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } @@ -61,13 +61,7 @@ impl GraphemeClusterBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } @@ -81,13 +75,7 @@ impl GraphemeClusterBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } } diff --git a/experimental/segmenter/src/lib.rs b/experimental/segmenter/src/lib.rs index 10d30ea4a3d..0dc3b66408b 100644 --- a/experimental/segmenter/src/lib.rs +++ b/experimental/segmenter/src/lib.rs @@ -67,7 +67,8 @@ //! //!```rust //! use icu_segmenter::GraphemeClusterBreakSegmenter; -//! let segmenter = GraphemeClusterBreakSegmenter::try_new() +//! let provider = icu_segmenter::RuleBreakDataProvider; +//! let segmenter = GraphemeClusterBreakSegmenter::try_new(&provider) //! .expect("Data exists"); //! //! let breakpoints: Vec = segmenter.segment_str("Hello 🗺").collect(); @@ -79,7 +80,8 @@ //! //! ```rust //! use icu_segmenter::GraphemeClusterBreakSegmenter; -//! let segmenter = GraphemeClusterBreakSegmenter::try_new() +//! let provider = icu_segmenter::RuleBreakDataProvider; +//! let segmenter = GraphemeClusterBreakSegmenter::try_new(&provider) //! .expect("Data exists"); //! //! let breakpoints: Vec = segmenter.segment_latin1(b"Hello World").collect(); @@ -92,7 +94,8 @@ //! //!```rust //! use icu_segmenter::WordBreakSegmenter; -//! let segmenter = WordBreakSegmenter::try_new() +//! let provider = icu_segmenter::RuleBreakDataProvider; +//! let segmenter = WordBreakSegmenter::try_new(&provider) //! .expect("Data exists"); //! //! let breakpoints: Vec = segmenter.segment_str("Hello World").collect(); @@ -103,7 +106,8 @@ //! //! ```rust //! use icu_segmenter::WordBreakSegmenter; -//! let segmenter = WordBreakSegmenter::try_new() +//! let provider = icu_segmenter::RuleBreakDataProvider; +//! let segmenter = WordBreakSegmenter::try_new(&provider) //! .expect("Data exists"); //! //! let breakpoints: Vec = segmenter.segment_latin1(b"Hello World").collect(); @@ -116,7 +120,8 @@ //! //!```rust //! use icu_segmenter::SentenceBreakSegmenter; -//! let segmenter = SentenceBreakSegmenter::try_new() +//! let provider = icu_segmenter::RuleBreakDataProvider; +//! let segmenter = SentenceBreakSegmenter::try_new(&provider) //! .expect("Data exists"); //! //! let breakpoints: Vec = segmenter.segment_str("Hello World").collect(); @@ -127,7 +132,8 @@ //! //! ```rust //! use icu_segmenter::SentenceBreakSegmenter; -//! let segmenter = SentenceBreakSegmenter::try_new() +//! let provider = icu_segmenter::RuleBreakDataProvider; +//! let segmenter = SentenceBreakSegmenter::try_new(&provider) //! .expect("Data exists"); //! //! let breakpoints: Vec = segmenter.segment_latin1(b"Hello World").collect(); @@ -147,7 +153,7 @@ mod line; mod sentence; mod word; -pub mod provider; +mod provider; #[cfg(feature = "lstm")] #[macro_use] @@ -174,6 +180,7 @@ pub use crate::grapheme::{ GraphemeClusterBreakIteratorUtf16, GraphemeClusterBreakSegmenter, }; pub use crate::line::*; +pub use crate::provider::RuleBreakDataProvider; pub use crate::sentence::{ SentenceBreakIterator, SentenceBreakIteratorLatin1, SentenceBreakIteratorUtf16, SentenceBreakSegmenter, diff --git a/experimental/segmenter/src/provider.rs b/experimental/segmenter/src/provider.rs index 906b2967eab..163b5f70180 100644 --- a/experimental/segmenter/src/provider.rs +++ b/experimental/segmenter/src/provider.rs @@ -11,7 +11,7 @@ use crate::line::PROPERTY_COUNT; use crate::line::PROPERTY_TABLE; use alloc::boxed::Box; use core::ops::Deref; -use icu_provider::{yoke, zerofrom}; +use icu_provider::prelude::*; use zerovec::ZeroSlice; use zerovec::ZeroVec; @@ -88,3 +88,158 @@ impl Default for LineBreakRuleTable<'static> { } } } + +/// Pre-processed Unicode data in the form of tables to be used for rule-based breaking. +#[icu_provider::data_struct( + WordBreakDataV1Marker = "segmenter/word@1", + GraphemeClusterBreakDataV1Marker = "segmenter/grapheme@1", + SentenceBreakDataV1Marker = "segmenter/sentence@1" +)] +#[derive(Debug, PartialEq, Clone)] +#[cfg_attr( + feature = "provider_serde", + derive(serde::Serialize, serde::Deserialize) +)] +pub struct RuleBreakDataV1<'data> { + /// Property table for rule-based breaking. + #[cfg_attr(feature = "provider_serde", serde(borrow))] + pub property_table: RuleBreakPropertyTable<'data>, + + /// Break state table for rule-based breaking. + #[cfg_attr(feature = "provider_serde", serde(borrow))] + pub break_state_table: RuleBreakStateTable<'data>, + + /// Number of properties; should be the square root of the length of [`Self::break_state_table`]. + pub property_count: u8, + + pub last_codepoint_property: i8, + pub sot_property: u8, + pub eot_property: u8, + pub complex_property: u8, +} + +/// Property table for rule-based breaking. +#[derive(Debug, PartialEq, Clone, yoke::Yokeable)] +#[cfg_attr( + feature = "provider_serde", + derive(serde::Serialize, serde::Deserialize) +)] +pub enum RuleBreakPropertyTable<'data> { + #[cfg_attr(feature = "provider_serde", serde(borrow))] + Borrowed(&'data [[u8; 1024]; 897]), + Owned(Box<[[u8; 1024]; 897]>), +} + +impl<'data> Deref for RuleBreakPropertyTable<'data> { + type Target = [[u8; 1024]; 897]; + fn deref(&self) -> &Self::Target { + match self { + Self::Borrowed(v) => v, + Self::Owned(v) => v, + } + } +} + +impl<'zf> zerofrom::ZeroFrom<'zf, RuleBreakPropertyTable<'_>> for RuleBreakPropertyTable<'zf> { + fn zero_from(cart: &'zf RuleBreakPropertyTable<'_>) -> Self { + RuleBreakPropertyTable::Borrowed(&*cart) + } +} + +/// Break state table for rule-based breaking. +#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)] +#[cfg_attr( + feature = "provider_serde", + derive(serde::Serialize, serde::Deserialize) +)] +pub struct RuleBreakStateTable<'data>(pub ZeroVec<'data, i8>); + +/// A provider to load static rule-based breaking data generated by build.rs. +pub struct RuleBreakDataProvider; + +mod grapheme_data { + include!(concat!(env!("OUT_DIR"), "/generated_grapheme_table.rs")); +} + +impl ResourceProvider for RuleBreakDataProvider { + fn load_resource( + &self, + _req: &DataRequest, + ) -> Result, DataError> { + let metadata = DataResponseMetadata::default(); + let data = RuleBreakDataV1 { + property_table: RuleBreakPropertyTable::Borrowed(&grapheme_data::PROPERTY_TABLE), + break_state_table: RuleBreakStateTable( + ZeroSlice::from_ule_slice(&grapheme_data::BREAK_STATE_MACHINE_TABLE).as_zerovec(), + ), + property_count: grapheme_data::PROPERTY_COUNT, + last_codepoint_property: grapheme_data::LAST_CODEPOINT_PROPERTY, + sot_property: grapheme_data::PROP_SOT, + eot_property: grapheme_data::PROP_EOT, + complex_property: grapheme_data::PROP_COMPLEX, + }; + + Ok(DataResponse { + metadata, + payload: Some(DataPayload::from_owned(data)), + }) + } +} + +mod word_data { + include!(concat!(env!("OUT_DIR"), "/generated_word_table.rs")); +} + +impl ResourceProvider for RuleBreakDataProvider { + fn load_resource( + &self, + _req: &DataRequest, + ) -> Result, DataError> { + let metadata = DataResponseMetadata::default(); + let data = RuleBreakDataV1 { + property_table: RuleBreakPropertyTable::Borrowed(&word_data::PROPERTY_TABLE), + break_state_table: RuleBreakStateTable( + ZeroSlice::from_ule_slice(&word_data::BREAK_STATE_MACHINE_TABLE).as_zerovec(), + ), + property_count: word_data::PROPERTY_COUNT, + last_codepoint_property: word_data::LAST_CODEPOINT_PROPERTY, + sot_property: word_data::PROP_SOT, + eot_property: word_data::PROP_EOT, + complex_property: word_data::PROP_COMPLEX, + }; + + Ok(DataResponse { + metadata, + payload: Some(DataPayload::from_owned(data)), + }) + } +} + +mod sentence_data { + include!(concat!(env!("OUT_DIR"), "/generated_sentence_table.rs")); +} + +impl ResourceProvider for RuleBreakDataProvider { + fn load_resource( + &self, + _req: &DataRequest, + ) -> Result, DataError> { + let metadata = DataResponseMetadata::default(); + let data = RuleBreakDataV1 { + property_table: RuleBreakPropertyTable::Borrowed(&sentence_data::PROPERTY_TABLE), + break_state_table: RuleBreakStateTable( + ZeroSlice::from_ule_slice(&sentence_data::BREAK_STATE_MACHINE_TABLE).as_zerovec(), + ), + property_count: sentence_data::PROPERTY_COUNT, + last_codepoint_property: sentence_data::LAST_CODEPOINT_PROPERTY, + sot_property: sentence_data::PROP_SOT, + eot_property: sentence_data::PROP_EOT, + complex_property: sentence_data::PROP_COMPLEX, + }; + + Ok(DataResponse { + metadata, + payload: Some(DataPayload::from_owned(data)), + }) + } +} diff --git a/experimental/segmenter/src/rule_segmenter.rs b/experimental/segmenter/src/rule_segmenter.rs index 2a362b7bebf..f1ee6e9e8cb 100644 --- a/experimental/segmenter/src/rule_segmenter.rs +++ b/experimental/segmenter/src/rule_segmenter.rs @@ -2,6 +2,8 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). +use crate::provider::RuleBreakDataV1; + // Note: Keep these constants in sync with build.rs. const NOT_MATCH_RULE: i8 = -2; const KEEP_RULE: i8 = -1; @@ -41,13 +43,7 @@ pub struct RuleBreakIterator<'l, 's, Y: RuleBreakType<'l, 's> + ?Sized> { pub(crate) len: usize, pub(crate) current_pos_data: Option<(usize, Y::CharType)>, pub(crate) result_cache: alloc::vec::Vec, - pub(crate) break_state_table: &'l [i8], - pub(crate) property_table: &'l [&'l [u8; 1024]; 897], - pub(crate) rule_property_count: usize, - pub(crate) last_codepoint_property: i8, - pub(crate) sot_property: u8, - pub(crate) eot_property: u8, - pub(crate) complex_property: u8, + pub(crate) data: &'l RuleBreakDataV1<'l>, } impl<'l, 's, Y: RuleBreakType<'l, 's>> Iterator for RuleBreakIterator<'l, 's, Y> { @@ -77,7 +73,7 @@ impl<'l, 's, Y: RuleBreakType<'l, 's>> Iterator for RuleBreakIterator<'l, 's, Y> self.current_pos_data = Some(current_pos_data); // SOT x anything let right_prop = self.get_current_break_property(); - if self.is_break_from_table(self.sot_property, right_prop) { + if self.is_break_from_table(self.data.sot_property, right_prop) { return Some(current_pos_data.0); } } @@ -94,8 +90,8 @@ impl<'l, 's, Y: RuleBreakType<'l, 's>> Iterator for RuleBreakIterator<'l, 's, Y> // Some segmenter rules doesn't have language-specific rules, we have to use LSTM (or dictionary) segmenter. // If property is marked as SA, use it - if right_prop == self.complex_property { - if left_prop != self.complex_property { + if right_prop == self.data.complex_property { + if left_prop != self.data.complex_property { // break before SA return Some(self.current_pos_data.unwrap().0); } @@ -118,7 +114,7 @@ impl<'l, 's, Y: RuleBreakType<'l, 's>> Iterator for RuleBreakIterator<'l, 's, Y> if self.current_pos_data.is_none() { // Reached EOF. But we are analyzing multiple characters now, so next break may be previous point. if self - .get_break_state_from_table(break_state as u8, self.eot_property as u8) + .get_break_state_from_table(break_state as u8, self.data.eot_property) == NOT_MATCH_RULE { self.iter = previous_iter; @@ -136,7 +132,7 @@ impl<'l, 's, Y: RuleBreakType<'l, 's>> Iterator for RuleBreakIterator<'l, 's, Y> break; } if previous_break_state >= 0 - && previous_break_state <= self.last_codepoint_property + && previous_break_state <= self.data.last_codepoint_property { // Move marker previous_iter = self.iter.clone(); @@ -183,11 +179,13 @@ impl<'l, 's, Y: RuleBreakType<'l, 's>> RuleBreakIterator<'l, 's, Y> { // Unknown return 0; } - self.property_table[codepoint / 1024][(codepoint & 0x3ff)] + self.data.property_table[codepoint / 1024][(codepoint & 0x3ff)] } fn get_break_state_from_table(&self, left: u8, right: u8) -> i8 { - self.break_state_table[(left as usize) * self.rule_property_count + (right as usize)] + let idx = left as usize * self.data.property_count as usize + right as usize; + // We use unwrap_or to fall back to the base case and prevent panics on bad data. + self.data.break_state_table.0.get(idx).unwrap_or(KEEP_RULE) } fn is_break_from_table(&self, left: u8, right: u8) -> bool { diff --git a/experimental/segmenter/src/sentence.rs b/experimental/segmenter/src/sentence.rs index 2accbbb004e..6f48914f7f0 100644 --- a/experimental/segmenter/src/sentence.rs +++ b/experimental/segmenter/src/sentence.rs @@ -4,13 +4,12 @@ use alloc::vec::Vec; use core::str::CharIndices; -use icu_provider::DataError; +use icu_provider::prelude::*; use crate::indices::{Latin1Indices, Utf16Indices}; +use crate::provider::*; use crate::rule_segmenter::*; -include!(concat!(env!("OUT_DIR"), "/generated_sentence_table.rs")); - /// Sentence break iterator for an `str` (a UTF-8 string). pub type SentenceBreakIterator<'l, 's> = RuleBreakIterator<'l, 's, SentenceBreakType>; @@ -24,12 +23,19 @@ pub type SentenceBreakIteratorUtf16<'l, 's> = RuleBreakIterator<'l, 's, Sentence /// encodings. Please see the [module-level documentation] for its usages. /// /// [module-level documentation]: index.html -pub struct SentenceBreakSegmenter; +pub struct SentenceBreakSegmenter { + payload: DataPayload, +} impl SentenceBreakSegmenter { - pub fn try_new() -> Result { - // Note: This will be able to return an Error once DataProvider is added - Ok(Self) + pub fn try_new(provider: &D) -> Result + where + D: ResourceProvider + ?Sized, + { + let payload = provider + .load_resource(&DataRequest::default())? + .take_payload()?; + Ok(Self { payload }) } /// Create a sentence break iterator for an `str` (a UTF-8 string). @@ -39,13 +45,7 @@ impl SentenceBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } @@ -59,13 +59,7 @@ impl SentenceBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } @@ -76,13 +70,7 @@ impl SentenceBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } } diff --git a/experimental/segmenter/src/word.rs b/experimental/segmenter/src/word.rs index 8f82c66981f..59580ec05f7 100644 --- a/experimental/segmenter/src/word.rs +++ b/experimental/segmenter/src/word.rs @@ -6,15 +6,14 @@ use alloc::string::String; use alloc::vec; use alloc::vec::Vec; use core::str::CharIndices; -use icu_provider::DataError; +use icu_provider::prelude::*; use crate::indices::{Latin1Indices, Utf16Indices}; use crate::lstm::get_line_break_utf16; use crate::lstm::get_line_break_utf8; +use crate::provider::*; use crate::rule_segmenter::*; -include!(concat!(env!("OUT_DIR"), "/generated_word_table.rs")); - fn get_complex_language_break(input: &[u16]) -> Vec { if let Some(mut ret) = get_line_break_utf16(input) { ret.push(input.len()); @@ -44,12 +43,19 @@ pub type WordBreakIteratorUtf16<'l, 's> = RuleBreakIterator<'l, 's, WordBreakTyp /// encodings. Please see the [module-level documentation] for its usages. /// /// [module-level documentation]: index.html -pub struct WordBreakSegmenter; +pub struct WordBreakSegmenter { + payload: DataPayload, +} impl WordBreakSegmenter { - pub fn try_new() -> Result { - // Note: This will be able to return an Error once DataProvider is added - Ok(Self) + pub fn try_new(provider: &D) -> Result + where + D: ResourceProvider + ?Sized, + { + let payload = provider + .load_resource(&DataRequest::default())? + .take_payload()?; + Ok(Self { payload }) } /// Create a word break iterator for an `str` (a UTF-8 string). @@ -59,13 +65,7 @@ impl WordBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } @@ -76,13 +76,7 @@ impl WordBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } @@ -93,13 +87,7 @@ impl WordBreakSegmenter { len: input.len(), current_pos_data: None, result_cache: Vec::new(), - break_state_table: &BREAK_STATE_MACHINE_TABLE, - property_table: &PROPERTY_TABLE, - rule_property_count: PROPERTY_COUNT, - last_codepoint_property: LAST_CODEPOINT_PROPERTY, - sot_property: PROP_SOT as u8, - eot_property: PROP_EOT as u8, - complex_property: PROP_COMPLEX as u8, + data: self.payload.get(), } } } @@ -129,7 +117,7 @@ impl<'l, 's> RuleBreakType<'l, 's> for WordBreakType { if iter.current_pos_data.is_none() { break; } - if iter.get_current_break_property() != iter.complex_property { + if iter.get_current_break_property() != iter.data.complex_property { break; } } @@ -203,7 +191,7 @@ impl<'l, 's> RuleBreakType<'l, 's> for WordBreakTypeUtf16 { if iter.current_pos_data.is_none() { break; } - if iter.get_current_break_property() != iter.complex_property { + if iter.get_current_break_property() != iter.data.complex_property { break; } } diff --git a/experimental/segmenter/tests/complex_word.rs b/experimental/segmenter/tests/complex_word.rs index 0eab853cc37..e50dd5cac76 100644 --- a/experimental/segmenter/tests/complex_word.rs +++ b/experimental/segmenter/tests/complex_word.rs @@ -2,13 +2,15 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). +use icu_segmenter::RuleBreakDataProvider; use icu_segmenter::WordBreakSegmenter; // Additional word segmenter tests with complex string. #[test] fn word_break_th() { - let segmenter = WordBreakSegmenter::try_new().expect("Data exists"); + let provider = RuleBreakDataProvider; + let segmenter = WordBreakSegmenter::try_new(&provider).expect("Data exists"); // http://wpt.live/css/css-text/word-break/word-break-normal-th-000.html let s = "ภาษาไทยภาษาไทย"; @@ -39,7 +41,8 @@ fn word_break_th() { #[test] fn word_break_my() { - let segmenter = WordBreakSegmenter::try_new().expect("Data exists"); + let provider = RuleBreakDataProvider; + let segmenter = WordBreakSegmenter::try_new(&provider).expect("Data exists"); let s = "မြန်မာစာမြန်မာစာမြန်မာစာ"; let utf16: Vec = s.encode_utf16().collect(); diff --git a/experimental/segmenter/tests/spec_test.rs b/experimental/segmenter/tests/spec_test.rs index 5798c380ba5..bb82f4b15c8 100644 --- a/experimental/segmenter/tests/spec_test.rs +++ b/experimental/segmenter/tests/spec_test.rs @@ -4,6 +4,7 @@ use icu_segmenter::GraphemeClusterBreakSegmenter; use icu_segmenter::LineBreakSegmenter; +use icu_segmenter::RuleBreakDataProvider; use icu_segmenter::SentenceBreakSegmenter; use icu_segmenter::WordBreakSegmenter; use std::char; @@ -138,7 +139,8 @@ fn run_line_break_test() { #[test] fn run_word_break_test() { let test_iter = TestContentIterator::new("./tests/testdata/WordBreakTest.txt"); - let segmenter = WordBreakSegmenter::try_new().expect("Data exists"); + let provider = RuleBreakDataProvider; + let segmenter = WordBreakSegmenter::try_new(&provider).expect("Data exists"); for test in test_iter { let s: String = test.utf8_vec.into_iter().collect(); let iter = segmenter.segment_str(&s); @@ -169,7 +171,8 @@ fn run_word_break_test() { #[test] fn run_grapheme_break_test() { let test_iter = TestContentIterator::new("./tests/testdata/GraphemeBreakTest.txt"); - let segmenter = GraphemeClusterBreakSegmenter::try_new().expect("Data exists"); + let provider = RuleBreakDataProvider; + let segmenter = GraphemeClusterBreakSegmenter::try_new(&provider).expect("Data exists"); for test in test_iter { let s: String = test.utf8_vec.into_iter().collect(); let iter = segmenter.segment_str(&s); @@ -200,7 +203,8 @@ fn run_grapheme_break_test() { #[test] fn run_sentence_break_test() { let test_iter = TestContentIterator::new("./tests/testdata/SentenceBreakTest.txt"); - let segmenter = SentenceBreakSegmenter::try_new().expect("Data exists"); + let provider = RuleBreakDataProvider; + let segmenter = SentenceBreakSegmenter::try_new(&provider).expect("Data exists"); for test in test_iter { let s: String = test.utf8_vec.into_iter().collect(); let iter = segmenter.segment_str(&s); From 5208806e15382eba7d0d033dace0cbdf64c242c6 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 23 Feb 2022 22:52:08 -0600 Subject: [PATCH 4/5] Update icu4x-announce link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9870e1c4eac..ec535eaa1ce 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The design goals of `ICU4X` are: * Availability and ease of use in multiple programming languages * Written by i18n experts to encourage best practices -***Stay informed!*** Join our public, low-traffic mailing list: [icu4x-announce@unicode.org](https://corp.unicode.org/mailman/listinfo/icu4x-announce). *Note: After subscribing, check your spam folder for a confirmation.* +***Stay informed!*** Join our public, low-traffic mailing list: [icu4x-announce@unicode.org](https://groups.google.com/u/1/a/unicode.org/g/icu4x-announce). *Note: After subscribing, check your spam folder for a confirmation.* ## Documentation From 00dd18c1dee952ed5336e7b12c8a353b7295209f Mon Sep 17 00:00:00 2001 From: Ting-Yu Lin Date: Thu, 24 Feb 2022 00:26:57 -0800 Subject: [PATCH 5/5] Fix a command name in icu_testdata docs (#1633) --- provider/testdata/README.md | 2 +- provider/testdata/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/provider/testdata/README.md b/provider/testdata/README.md index 0c71ec2a162..ca2b7e310e3 100644 --- a/provider/testdata/README.md +++ b/provider/testdata/README.md @@ -33,7 +33,7 @@ The following commands are also available: - `cargo make testdata-download` downloads fresh CLDR JSON - `cargo make testdata-build-json` re-generates the ICU4X JSON - `cargo make testdata-build-blob` re-generates the ICU4X blob file -- `cargo make bincode-gen-testdata` generates Bincode filesystem testdata +- `cargo make testdata-build-bincode` re-generates Bincode filesystem testdata ## Examples diff --git a/provider/testdata/src/lib.rs b/provider/testdata/src/lib.rs index 408780f5ce5..a75987027b0 100644 --- a/provider/testdata/src/lib.rs +++ b/provider/testdata/src/lib.rs @@ -35,7 +35,7 @@ //! - `cargo make testdata-download` downloads fresh CLDR JSON //! - `cargo make testdata-build-json` re-generates the ICU4X JSON //! - `cargo make testdata-build-blob` re-generates the ICU4X blob file -//! - `cargo make bincode-gen-testdata` generates Bincode filesystem testdata +//! - `cargo make testdata-build-bincode` re-generates Bincode filesystem testdata //! //! # Examples //!