github.com/graemephi/kahugo@v0.62.3-0.20211121071557-d78c0423784d/common/htime/time.go (about) 1 // Copyright 2021 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package htime 15 16 import ( 17 "strings" 18 "time" 19 20 "github.com/spf13/cast" 21 22 toml "github.com/pelletier/go-toml/v2" 23 24 "github.com/gohugoio/locales" 25 ) 26 27 var ( 28 longDayNames = []string{ 29 "Sunday", 30 "Monday", 31 "Tuesday", 32 "Wednesday", 33 "Thursday", 34 "Friday", 35 "Saturday", 36 } 37 38 shortDayNames = []string{ 39 "Sun", 40 "Mon", 41 "Tue", 42 "Wed", 43 "Thu", 44 "Fri", 45 "Sat", 46 } 47 48 shortMonthNames = []string{ 49 "Jan", 50 "Feb", 51 "Mar", 52 "Apr", 53 "May", 54 "Jun", 55 "Jul", 56 "Aug", 57 "Sep", 58 "Oct", 59 "Nov", 60 "Dec", 61 } 62 63 longMonthNames = []string{ 64 "January", 65 "February", 66 "March", 67 "April", 68 "May", 69 "June", 70 "July", 71 "August", 72 "September", 73 "October", 74 "November", 75 "December", 76 } 77 ) 78 79 func NewTimeFormatter(ltr locales.Translator) TimeFormatter { 80 if ltr == nil { 81 panic("must provide a locales.Translator") 82 } 83 return TimeFormatter{ 84 ltr: ltr, 85 } 86 } 87 88 // TimeFormatter is locale aware. 89 type TimeFormatter struct { 90 ltr locales.Translator 91 } 92 93 func (f TimeFormatter) Format(t time.Time, layout string) string { 94 if layout == "" { 95 return "" 96 } 97 98 if layout[0] == ':' { 99 // It may be one of Hugo's custom layouts. 100 switch strings.ToLower(layout[1:]) { 101 case "date_full": 102 return f.ltr.FmtDateFull(t) 103 case "date_long": 104 return f.ltr.FmtDateLong(t) 105 case "date_medium": 106 return f.ltr.FmtDateMedium(t) 107 case "date_short": 108 return f.ltr.FmtDateShort(t) 109 case "time_full": 110 return f.ltr.FmtTimeFull(t) 111 case "time_long": 112 return f.ltr.FmtTimeLong(t) 113 case "time_medium": 114 return f.ltr.FmtTimeMedium(t) 115 case "time_short": 116 return f.ltr.FmtTimeShort(t) 117 } 118 } 119 120 s := t.Format(layout) 121 122 monthIdx := t.Month() - 1 // Month() starts at 1. 123 dayIdx := t.Weekday() 124 125 s = strings.ReplaceAll(s, longMonthNames[monthIdx], f.ltr.MonthWide(t.Month())) 126 if !strings.Contains(s, f.ltr.MonthWide(t.Month())) { 127 s = strings.ReplaceAll(s, shortMonthNames[monthIdx], f.ltr.MonthAbbreviated(t.Month())) 128 } 129 s = strings.ReplaceAll(s, longDayNames[dayIdx], f.ltr.WeekdayWide(t.Weekday())) 130 if !strings.Contains(s, f.ltr.WeekdayWide(t.Weekday())) { 131 s = strings.ReplaceAll(s, shortDayNames[dayIdx], f.ltr.WeekdayAbbreviated(t.Weekday())) 132 } 133 134 return s 135 } 136 137 func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) { 138 switch vv := i.(type) { 139 case toml.LocalDate: 140 return vv.AsTime(location), nil 141 case toml.LocalDateTime: 142 return vv.AsTime(location), nil 143 // issue #8895 144 // datetimes parsed by `go-toml` have empty zone name 145 // convert back them into string and use `cast` 146 case time.Time: 147 i = vv.Format(time.RFC3339) 148 } 149 return cast.ToTimeInDefaultLocationE(i, location) 150 }