A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
at lambda-fork/main 246 lines 7.0 kB view raw
1// SiYuan - Refactor your thinking 2// Copyright (c) 2020-present, b3log.org 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU Affero General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU Affero General Public License for more details. 13// 14// You should have received a copy of the GNU Affero General Public License 15// along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17package util 18 19import ( 20 "bytes" 21 "fmt" 22 "math" 23 "strings" 24 "time" 25 26 "github.com/88250/go-humanize" 27) 28 29func IsTimeStr(str string) bool { 30 _, err := time.Parse("20060102150405", str) 31 return nil == err 32} 33 34func GetTodayStart() (ret time.Time) { 35 ret = time.Now() 36 ret = time.Date(ret.Year(), ret.Month(), ret.Day(), 0, 0, 0, 0, time.Local) 37 return 38} 39 40// Weekday returns the day of the week specified by date. 41// Sunday=0, Monday=1, ..., Saturday=6. 42func Weekday(date time.Time) int { 43 return int(date.Weekday()) 44} 45 46// WeekdayCN returns the day of the week specified by date. 47// Sunday=日, Monday=一, ..., Saturday=六. 48func WeekdayCN(date time.Time) string { 49 week := Weekday(date) 50 weekdayCN := []string{"日", "一", "二", "三", "四", "五", "六"} 51 return weekdayCN[week] 52} 53 54// WeekdayCN2 returns the day of the week specified by date. 55// Sunday=天, Monday=一, ..., Saturday=六. 56func WeekdayCN2(date time.Time) string { 57 week := Weekday(date) 58 weekdayCN2 := []string{"天", "一", "二", "三", "四", "五", "六"} 59 return weekdayCN2[week] 60} 61 62// ISOWeek returns the ISO 8601 week number in which date occurs. 63// Week ranges from 1 to 53. Jan 01 to Jan 03 of year n might belong to week 52 or 53 of year n-1, 64// and Dec 29 to Dec 31 might belong to week 1 of year n+1. 65func ISOWeek(date time.Time) int { 66 _, week := date.ISOWeek() 67 return week 68} 69 70// ISOYear returns the ISO 8601 year in which date occurs. 71func ISOYear(date time.Time) int { 72 year, _ := date.ISOWeek() 73 return year 74} 75 76// ISOMonth returns the month in which the Thursday of the ISO 8601 week of date occurs. 77func ISOMonth(date time.Time) int { 78 isoYear, isoWeek := date.ISOWeek() 79 80 // 1. 找到该 ISO 年份的 1 月 4 日(它必然属于第 1 周) 81 jan4 := time.Date(isoYear, time.January, 4, 0, 0, 0, 0, date.Location()) 82 83 // 2. 找到第 1 周的周四 84 // (jan4.Weekday() + 6) % 7 将周一~周日映射为 0~6 85 daysToMonday := (int(jan4.Weekday()) + 6) % 7 86 mondayOfWeek1 := jan4.AddDate(0, 0, -daysToMonday) 87 thursdayOfWeek1 := mondayOfWeek1.AddDate(0, 0, 3) 88 89 // 3. 计算目标周的周四 90 // 目标周四 = 第一周周四 + (isoWeek-1) * 7天 91 targetThursday := thursdayOfWeek1.AddDate(0, 0, (isoWeek-1)*7) 92 93 // 4. 返回该周四所在的自然月份 94 return int(targetThursday.Month()) 95} 96 97// ISOWeekDate returns the date of the specified day of the week in the ISO 8601 week of date. 98// day: Monday=1, ..., Sunday=7. 99func ISOWeekDate(day int, date time.Time) time.Time { 100 weekday := int(date.Weekday()) 101 if weekday == 0 { 102 weekday = 7 103 } 104 105 daysToMonday := weekday - 1 106 monday := date.AddDate(0, 0, -daysToMonday) 107 return monday.AddDate(0, 0, day-1) 108} 109 110func Millisecond2Time(t int64) time.Time { 111 sec := t / 1000 112 msec := t % 1000 113 return time.Unix(sec, msec*int64(time.Millisecond)) 114} 115 116func CurrentTimeMillis() int64 { 117 return time.Now().UnixMilli() 118} 119 120func CurrentTimeSecondsStr() string { 121 return time.Now().Format("20060102150405") 122} 123 124func HumanizeDiffTime(a, b time.Time, lang string) string { 125 labels := TimeLangs[lang] 126 year, month, day, hour, min, _ := humanizeDiffTime(a, b) 127 buf := bytes.Buffer{} 128 if 0 < year { 129 if 1 == year { 130 buf.WriteString(fmt.Sprintf(labels["1y"].(string), " ")) 131 } else { 132 buf.WriteString(fmt.Sprintf(labels["xy"].(string), year, " ")) 133 } 134 } 135 if 0 < month { 136 if 1 == month { 137 buf.WriteString(fmt.Sprintf(labels["1M"].(string), " ")) 138 } else { 139 buf.WriteString(fmt.Sprintf(labels["xM"].(string), month, " ")) 140 } 141 } 142 if 0 < day { 143 if 1 == day { 144 buf.WriteString(fmt.Sprintf(labels["1d"].(string), " ")) 145 } else { 146 buf.WriteString(fmt.Sprintf(labels["xd"].(string), day, " ")) 147 } 148 } 149 if 0 < hour { 150 if 1 == hour { 151 buf.WriteString(fmt.Sprintf(labels["1h"].(string), " ")) 152 } else { 153 buf.WriteString(fmt.Sprintf(labels["xh"].(string), hour, " ")) 154 } 155 } 156 if 0 < min { 157 if 1 == min { 158 buf.WriteString(fmt.Sprintf(labels["1m"].(string), " ")) 159 } else { 160 buf.WriteString(fmt.Sprintf(labels["xm"].(string), min, " ")) 161 } 162 } 163 return strings.TrimSpace(buf.String()) 164} 165 166func humanizeDiffTime(a, b time.Time) (year, month, day, hour, min, sec int) { 167 // 感谢 https://stackoverflow.com/a/36531443/1043233 168 169 if a.Location() != b.Location() { 170 b = b.In(a.Location()) 171 } 172 if a.After(b) { 173 a, b = b, a 174 } 175 y1, M1, d1 := a.Date() 176 y2, M2, d2 := b.Date() 177 178 h1, m1, s1 := a.Clock() 179 h2, m2, s2 := b.Clock() 180 181 year = y2 - y1 182 month = int(M2 - M1) 183 day = d2 - d1 184 hour = h2 - h1 185 min = m2 - m1 186 sec = s2 - s1 187 188 // Normalize negative values 189 if sec < 0 { 190 sec += 60 191 min-- 192 } 193 if min < 0 { 194 min += 60 195 hour-- 196 } 197 if hour < 0 { 198 hour += 24 199 day-- 200 } 201 if day < 0 { 202 // days in month: 203 t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC) 204 day += 32 - t.Day() 205 month-- 206 } 207 if month < 0 { 208 month += 12 209 year-- 210 } 211 return 212} 213 214func HumanizeRelTime(a time.Time, b time.Time, lang string) string { 215 _, magnitudes := humanizeTimeMagnitudes(lang) 216 return strings.TrimSpace(humanize.CustomRelTime(a, b, "", "", magnitudes)) 217} 218 219func HumanizeTime(then time.Time, lang string) string { 220 labels, magnitudes := humanizeTimeMagnitudes(lang) 221 return strings.TrimSpace(humanize.CustomRelTime(then, time.Now(), labels["albl"].(string), labels["blbl"].(string), magnitudes)) 222} 223 224func humanizeTimeMagnitudes(lang string) (labels map[string]interface{}, magnitudes []humanize.RelTimeMagnitude) { 225 labels = TimeLangs[lang] 226 magnitudes = []humanize.RelTimeMagnitude{ 227 {time.Second, labels["now"].(string), time.Second}, 228 {2 * time.Second, labels["1s"].(string), 1}, 229 {time.Minute, labels["xs"].(string), time.Second}, 230 {2 * time.Minute, labels["1m"].(string), 1}, 231 {time.Hour, labels["xm"].(string), time.Minute}, 232 {2 * time.Hour, labels["1h"].(string), 1}, 233 {humanize.Day, labels["xh"].(string), time.Hour}, 234 {2 * humanize.Day, labels["1d"].(string), 1}, 235 {humanize.Week, labels["xd"].(string), humanize.Day}, 236 {2 * humanize.Week, labels["1w"].(string), 1}, 237 {humanize.Month, labels["xw"].(string), humanize.Week}, 238 {2 * humanize.Month, labels["1M"].(string), 1}, 239 {humanize.Year, labels["xM"].(string), humanize.Month}, 240 {23 * humanize.Month, labels["1y"].(string), 1}, 241 {2 * humanize.Year, labels["2y"].(string), 1}, 242 {humanize.LongTime, labels["xy"].(string), humanize.Year}, 243 {math.MaxInt64, labels["max"].(string), 1}, 244 } 245 return 246}