github.com/anakojm/hugo-katex@v0.0.0-20231023141351-42d6f5de9c0b/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 "log" 18 "strings" 19 "time" 20 21 "github.com/bep/clocks" 22 "github.com/spf13/cast" 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 Clock = clocks.System() 79 ) 80 81 func NewTimeFormatter(ltr locales.Translator) TimeFormatter { 82 if ltr == nil { 83 panic("must provide a locales.Translator") 84 } 85 return TimeFormatter{ 86 ltr: ltr, 87 } 88 } 89 90 // TimeFormatter is locale aware. 91 type TimeFormatter struct { 92 ltr locales.Translator 93 } 94 95 func (f TimeFormatter) Format(t time.Time, layout string) string { 96 if layout == "" { 97 return "" 98 } 99 100 if layout[0] == ':' { 101 // It may be one of Hugo's custom layouts. 102 switch strings.ToLower(layout[1:]) { 103 case "date_full": 104 return f.ltr.FmtDateFull(t) 105 case "date_long": 106 return f.ltr.FmtDateLong(t) 107 case "date_medium": 108 return f.ltr.FmtDateMedium(t) 109 case "date_short": 110 return f.ltr.FmtDateShort(t) 111 case "time_full": 112 return f.ltr.FmtTimeFull(t) 113 case "time_long": 114 return f.ltr.FmtTimeLong(t) 115 case "time_medium": 116 return f.ltr.FmtTimeMedium(t) 117 case "time_short": 118 return f.ltr.FmtTimeShort(t) 119 } 120 } 121 122 s := t.Format(layout) 123 124 monthIdx := t.Month() - 1 // Month() starts at 1. 125 dayIdx := t.Weekday() 126 127 if strings.Contains(layout, "January") { 128 s = strings.ReplaceAll(s, longMonthNames[monthIdx], f.ltr.MonthWide(t.Month())) 129 } else if strings.Contains(layout, "Jan") { 130 s = strings.ReplaceAll(s, shortMonthNames[monthIdx], f.ltr.MonthAbbreviated(t.Month())) 131 } 132 133 if strings.Contains(layout, "Monday") { 134 s = strings.ReplaceAll(s, longDayNames[dayIdx], f.ltr.WeekdayWide(t.Weekday())) 135 } else if strings.Contains(layout, "Mon") { 136 s = strings.ReplaceAll(s, shortDayNames[dayIdx], f.ltr.WeekdayAbbreviated(t.Weekday())) 137 } 138 139 return s 140 } 141 142 func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, err error) { 143 switch vv := i.(type) { 144 case AsTimeProvider: 145 return vv.AsTime(location), nil 146 // issue #8895 147 // datetimes parsed by `go-toml` have empty zone name 148 // convert back them into string and use `cast` 149 // TODO(bep) add tests, make sure we really need this. 150 case time.Time: 151 i = vv.Format(time.RFC3339) 152 } 153 return cast.ToTimeInDefaultLocationE(i, location) 154 } 155 156 // Now returns time.Now() or time value based on the `clock` flag. 157 // Use this function to fake time inside hugo. 158 func Now() time.Time { 159 return Clock.Now() 160 } 161 162 func Since(t time.Time) time.Duration { 163 return Clock.Since(t) 164 } 165 166 // AsTimeProvider is implemented by go-toml's LocalDate and LocalDateTime. 167 type AsTimeProvider interface { 168 AsTime(zone *time.Location) time.Time 169 } 170 171 // StopWatch is a simple helper to measure time during development. 172 func StopWatch(name string) func() { 173 start := time.Now() 174 return func() { 175 log.Printf("StopWatch %q took %s", name, time.Since(start)) 176 } 177 }