1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:build ignore 6// +build ignore 7 8package main 9 10import ( 11 "flag" 12 "log" 13 "strconv" 14 "strings" 15 16 "golang.org/x/text/internal/cldrtree" 17 "golang.org/x/text/internal/gen" 18 "golang.org/x/text/language" 19 "golang.org/x/text/unicode/cldr" 20) 21 22var ( 23 draft = flag.String("draft", 24 "contributed", 25 `Minimal draft requirements (approved, contributed, provisional, unconfirmed).`) 26) 27 28// TODO: 29// - Compile format patterns. 30// - Compress the large amount of redundancy in metazones. 31// - Split trees (with shared buckets) with data that is enough for default 32// formatting of Go Time values and tables that are needed for larger 33// variants. 34// - zone to metaZone mappings (in supplemental) 35// - Add more enum values and also some key maps for some of the elements. 36 37func main() { 38 gen.Init() 39 40 r := gen.OpenCLDRCoreZip() 41 defer r.Close() 42 43 d := &cldr.Decoder{} 44 d.SetDirFilter("supplemental", "main") 45 d.SetSectionFilter("dates") 46 data, err := d.DecodeZip(r) 47 if err != nil { 48 log.Fatalf("DecodeZip: %v", err) 49 } 50 51 dates := cldrtree.New("dates") 52 buildCLDRTree(data, dates) 53 54 w := gen.NewCodeWriter() 55 if err := dates.Gen(w); err != nil { 56 log.Fatal(err) 57 } 58 gen.WriteCLDRVersion(w) 59 w.WriteGoFile("tables.go", "date") 60 61 w = gen.NewCodeWriter() 62 if err := dates.GenTestData(w); err != nil { 63 log.Fatal(err) 64 } 65 w.WriteGoFile("data_test.go", "date") 66} 67 68func buildCLDRTree(data *cldr.CLDR, dates *cldrtree.Builder) { 69 context := cldrtree.Enum("context") 70 widthMap := func(s string) string { 71 // Align era with width values. 72 if r, ok := map[string]string{ 73 "eraAbbr": "abbreviated", 74 "eraNarrow": "narrow", 75 "eraNames": "wide", 76 }[s]; ok { 77 s = r 78 } 79 // Prefix width to disambiguate with some overlapping length values. 80 return "width" + strings.Title(s) 81 } 82 width := cldrtree.EnumFunc("width", widthMap, "abbreviated", "narrow", "wide") 83 length := cldrtree.Enum("length", "short", "long") 84 month := cldrtree.Enum("month", "leap7") 85 relTime := cldrtree.EnumFunc("relTime", func(s string) string { 86 x, err := strconv.ParseInt(s, 10, 8) 87 if err != nil { 88 log.Fatal("Invalid number:", err) 89 } 90 return []string{ 91 "before2", 92 "before1", 93 "current", 94 "after1", 95 "after2", 96 "after3", 97 }[x+2] 98 }) 99 // Disambiguate keys like 'months' and 'sun'. 100 cycleType := cldrtree.EnumFunc("cycleType", func(s string) string { 101 return s + "CycleType" 102 }) 103 field := cldrtree.EnumFunc("field", func(s string) string { 104 return s + "Field" 105 }) 106 timeType := cldrtree.EnumFunc("timeType", func(s string) string { 107 if s == "" { 108 return "genericTime" 109 } 110 return s + "Time" 111 }, "generic") 112 113 zoneType := []cldrtree.Option{cldrtree.SharedType(), timeType} 114 metaZoneType := []cldrtree.Option{cldrtree.SharedType(), timeType} 115 116 for _, lang := range data.Locales() { 117 tag := language.Make(lang) 118 ldml := data.RawLDML(lang) 119 if ldml.Dates == nil { 120 continue 121 } 122 x := dates.Locale(tag) 123 if x := x.Index(ldml.Dates.Calendars); x != nil { 124 for _, cal := range ldml.Dates.Calendars.Calendar { 125 x := x.IndexFromType(cal) 126 if x := x.Index(cal.Months); x != nil { 127 for _, mc := range cal.Months.MonthContext { 128 x := x.IndexFromType(mc, context) 129 for _, mw := range mc.MonthWidth { 130 x := x.IndexFromType(mw, width) 131 for _, m := range mw.Month { 132 x.SetValue(m.Yeartype+m.Type, m, month) 133 } 134 } 135 } 136 } 137 if x := x.Index(cal.MonthPatterns); x != nil { 138 for _, mc := range cal.MonthPatterns.MonthPatternContext { 139 x := x.IndexFromType(mc, context) 140 for _, mw := range mc.MonthPatternWidth { 141 // Value is always leap, so no need to create a 142 // subindex. 143 for _, m := range mw.MonthPattern { 144 x.SetValue(mw.Type, m, width) 145 } 146 } 147 } 148 } 149 if x := x.Index(cal.CyclicNameSets); x != nil { 150 for _, cns := range cal.CyclicNameSets.CyclicNameSet { 151 x := x.IndexFromType(cns, cycleType) 152 for _, cc := range cns.CyclicNameContext { 153 x := x.IndexFromType(cc, context) 154 for _, cw := range cc.CyclicNameWidth { 155 x := x.IndexFromType(cw, width) 156 for _, c := range cw.CyclicName { 157 x.SetValue(c.Type, c) 158 } 159 } 160 } 161 } 162 } 163 if x := x.Index(cal.Days); x != nil { 164 for _, dc := range cal.Days.DayContext { 165 x := x.IndexFromType(dc, context) 166 for _, dw := range dc.DayWidth { 167 x := x.IndexFromType(dw, width) 168 for _, d := range dw.Day { 169 x.SetValue(d.Type, d) 170 } 171 } 172 } 173 } 174 if x := x.Index(cal.Quarters); x != nil { 175 for _, qc := range cal.Quarters.QuarterContext { 176 x := x.IndexFromType(qc, context) 177 for _, qw := range qc.QuarterWidth { 178 x := x.IndexFromType(qw, width) 179 for _, q := range qw.Quarter { 180 x.SetValue(q.Type, q) 181 } 182 } 183 } 184 } 185 if x := x.Index(cal.DayPeriods); x != nil { 186 for _, dc := range cal.DayPeriods.DayPeriodContext { 187 x := x.IndexFromType(dc, context) 188 for _, dw := range dc.DayPeriodWidth { 189 x := x.IndexFromType(dw, width) 190 for _, d := range dw.DayPeriod { 191 x.IndexFromType(d).SetValue(d.Alt, d) 192 } 193 } 194 } 195 } 196 if x := x.Index(cal.Eras); x != nil { 197 opts := []cldrtree.Option{width, cldrtree.SharedType()} 198 if x := x.Index(cal.Eras.EraNames, opts...); x != nil { 199 for _, e := range cal.Eras.EraNames.Era { 200 x.IndexFromAlt(e).SetValue(e.Type, e) 201 } 202 } 203 if x := x.Index(cal.Eras.EraAbbr, opts...); x != nil { 204 for _, e := range cal.Eras.EraAbbr.Era { 205 x.IndexFromAlt(e).SetValue(e.Type, e) 206 } 207 } 208 if x := x.Index(cal.Eras.EraNarrow, opts...); x != nil { 209 for _, e := range cal.Eras.EraNarrow.Era { 210 x.IndexFromAlt(e).SetValue(e.Type, e) 211 } 212 } 213 } 214 if x := x.Index(cal.DateFormats); x != nil { 215 for _, dfl := range cal.DateFormats.DateFormatLength { 216 x := x.IndexFromType(dfl, length) 217 for _, df := range dfl.DateFormat { 218 for _, p := range df.Pattern { 219 x.SetValue(p.Alt, p) 220 } 221 } 222 } 223 } 224 if x := x.Index(cal.TimeFormats); x != nil { 225 for _, tfl := range cal.TimeFormats.TimeFormatLength { 226 x := x.IndexFromType(tfl, length) 227 for _, tf := range tfl.TimeFormat { 228 for _, p := range tf.Pattern { 229 x.SetValue(p.Alt, p) 230 } 231 } 232 } 233 } 234 if x := x.Index(cal.DateTimeFormats); x != nil { 235 for _, dtfl := range cal.DateTimeFormats.DateTimeFormatLength { 236 x := x.IndexFromType(dtfl, length) 237 for _, dtf := range dtfl.DateTimeFormat { 238 for _, p := range dtf.Pattern { 239 x.SetValue(p.Alt, p) 240 } 241 } 242 } 243 // TODO: 244 // - appendItems 245 // - intervalFormats 246 } 247 } 248 } 249 // TODO: this is a lot of data and is probably relatively little used. 250 // Store this somewhere else. 251 if x := x.Index(ldml.Dates.Fields); x != nil { 252 for _, f := range ldml.Dates.Fields.Field { 253 x := x.IndexFromType(f, field) 254 for _, d := range f.DisplayName { 255 x.Index(d).SetValue(d.Alt, d) 256 } 257 for _, r := range f.Relative { 258 x.Index(r).SetValue(r.Type, r, relTime) 259 } 260 for _, rt := range f.RelativeTime { 261 x := x.Index(rt).IndexFromType(rt) 262 for _, p := range rt.RelativeTimePattern { 263 x.SetValue(p.Count, p) 264 } 265 } 266 for _, rp := range f.RelativePeriod { 267 x.Index(rp).SetValue(rp.Alt, rp) 268 } 269 } 270 } 271 if x := x.Index(ldml.Dates.TimeZoneNames); x != nil { 272 format := x.IndexWithName("zoneFormat") 273 for _, h := range ldml.Dates.TimeZoneNames.HourFormat { 274 format.SetValue(h.Element(), h) 275 } 276 for _, g := range ldml.Dates.TimeZoneNames.GmtFormat { 277 format.SetValue(g.Element(), g) 278 } 279 for _, g := range ldml.Dates.TimeZoneNames.GmtZeroFormat { 280 format.SetValue(g.Element(), g) 281 } 282 for _, r := range ldml.Dates.TimeZoneNames.RegionFormat { 283 x.Index(r).SetValue(r.Type, r, timeType) 284 } 285 286 set := func(x *cldrtree.Index, e []*cldr.Common, zone string) { 287 for _, n := range e { 288 x.Index(n, zoneType...).SetValue(zone, n) 289 } 290 } 291 zoneWidth := []cldrtree.Option{length, cldrtree.SharedType()} 292 zs := x.IndexWithName("zone") 293 for _, z := range ldml.Dates.TimeZoneNames.Zone { 294 for _, l := range z.Long { 295 x := zs.Index(l, zoneWidth...) 296 set(x, l.Generic, z.Type) 297 set(x, l.Standard, z.Type) 298 set(x, l.Daylight, z.Type) 299 } 300 for _, s := range z.Short { 301 x := zs.Index(s, zoneWidth...) 302 set(x, s.Generic, z.Type) 303 set(x, s.Standard, z.Type) 304 set(x, s.Daylight, z.Type) 305 } 306 } 307 set = func(x *cldrtree.Index, e []*cldr.Common, zone string) { 308 for _, n := range e { 309 x.Index(n, metaZoneType...).SetValue(zone, n) 310 } 311 } 312 zoneWidth = []cldrtree.Option{length, cldrtree.SharedType()} 313 zs = x.IndexWithName("metaZone") 314 for _, z := range ldml.Dates.TimeZoneNames.Metazone { 315 for _, l := range z.Long { 316 x := zs.Index(l, zoneWidth...) 317 set(x, l.Generic, z.Type) 318 set(x, l.Standard, z.Type) 319 set(x, l.Daylight, z.Type) 320 } 321 for _, s := range z.Short { 322 x := zs.Index(s, zoneWidth...) 323 set(x, s.Generic, z.Type) 324 set(x, s.Standard, z.Type) 325 set(x, s.Daylight, z.Type) 326 } 327 } 328 } 329 } 330} 331