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