github.com/zhongdalu/gf@v1.0.0/g/os/gtime/gtime_format.go (about) 1 // Copyright 2018 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package gtime 8 9 import ( 10 "bytes" 11 "strconv" 12 "strings" 13 14 "github.com/zhongdalu/gf/g/text/gregex" 15 ) 16 17 var ( 18 // 参考:http://php.net/manual/zh/function.date.php 19 formats = map[byte]string{ 20 // ================== 日 ================== 21 'd': "02", // 月份中的第几天,有前导零的 2 位数字(01 到 31) 22 'D': "Mon", // 星期中的第几天,文本表示,3 个字母(Mon 到 Sun) 23 'w': "Monday", // 星期中的第几天,数字型式的文本表示 0为星期天 6为星期六 24 'N': "Monday", // ISO-8601 格式数字表示的星期中的第几天 1(表示星期一)到 7(表示星期天) 25 'j': "=j=02", // 月份中的第几天,没有前导零(1 到 31) 26 'S': "02", // 每月天数后面的英文后缀,2 个字符 st,nd,rd 或者 th。可以和 j 一起用 27 'l': "Monday", // ("L"的小写字母)星期几,完整的文本格式(Sunday 到 Saturday) 28 'z': "", // 年份中的第几天 0到365 29 30 // ================== 日 ================== 31 'W': "", // ISO-8601 格式年份中的第几周,每周从星期一开始 例如:42(当年的第 42 周) 32 33 // ================== 月 ================== 34 'F': "January", // 月份,完整的文本格式,例如 January 或者 March January 到 December 35 'm': "01", // 数字表示的月份,有前导零(01 到 12) 36 'M': "Jan", // 三个字母缩写表示的月份(Jan 到 Dec) 37 'n': "1", // 数字表示的月份,没有前导零(1 到 12) 38 't': "", // 指定的月份有几天 28到31 39 40 // ================== 年 ================== 41 'Y': "2006", // 4 位数字完整表示的年份, 例如:1999 或 2003 42 'y': "06", // 2 位数字表示的年份, 例如:99 或 03 43 44 // ================== 时间 ================== 45 'a': "pm", // 小写的上午和下午值 am 或 pm 46 'A': "PM", // 大写的上午和下午值 AM 或 PM 47 'g': "3", // 小时,12 小时格式,没有前导零, 1 到 12 48 'G': "=G=15", // 小时,24 小时格式,没有前导零, 0 到 23 49 'h': "03", // 小时,12 小时格式,有前导零, 01 到 12 50 'H': "15", // 小时,24 小时格式,有前导零, 00 到 23 51 'i': "04", // 有前导零的分钟数, 00 到 59 52 's': "05", // 秒数,有前导零, 00 到 59 53 'u': "=u=.000", // 毫秒(3位) 54 'U': "", // 将时间格式化为Unix时间,即从时间点January 1, 1970 UTC到时间点t所经过的时间(单位秒) 55 56 // ================== 时区 ================== 57 'O': "-0700", // 与UTC相差的小时数, 例如:+0200 58 'P': "-07:00", // 与UTC的差别,小时和分钟之间有冒号分隔, 例如:+02:00 59 'T': "MST", // 时区缩写, 例如: UTC, EST, MDT 60 61 // ================== 完整的日期/时间 ================== 62 'c': "2006-01-02T15:04:05-07:00", // ISO 8601 格式的日期,例如:2004-02-12T15:19:21+00:00 63 'r': "Mon, 02 Jan 06 15:04 MST", // RFC 822 格式的日期,例如:Thu, 21 Dec 2000 16:01:07 +0200 64 } 65 66 // 星期的英文值和数字值对应map 67 weekMap = map[string]string{ 68 "Sunday": "0", 69 "Monday": "1", 70 "Tuesday": "2", 71 "Wednesday": "3", 72 "Thursday": "4", 73 "Friday": "5", 74 "Saturday": "6", 75 } 76 77 // 每个月累计的天数 不含润年的时候 78 dayOfMonth = []int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334} 79 ) 80 81 // 使用自定义日期格式格式化输出日期。 82 func (t *Time) Format(format string) string { 83 runes := []rune(format) 84 buffer := bytes.NewBuffer(nil) 85 for i := 0; i < len(runes); { 86 switch runes[i] { 87 case '\\': 88 if i < len(runes)-1 { 89 buffer.WriteRune(runes[i+1]) 90 i += 2 91 continue 92 } else { 93 return buffer.String() 94 } 95 case 'W': 96 buffer.WriteString(strconv.Itoa(t.WeeksOfYear())) 97 case 'z': 98 buffer.WriteString(strconv.Itoa(t.DayOfYear())) 99 case 't': 100 buffer.WriteString(strconv.Itoa(t.DaysInMonth())) 101 case 'U': 102 buffer.WriteString(strconv.FormatInt(t.Unix(), 10)) 103 default: 104 if runes[i] > 255 { 105 buffer.WriteRune(runes[i]) 106 break 107 } 108 if f, ok := formats[byte(runes[i])]; ok { 109 result := t.Time.Format(f) 110 // 有几个转换的符号需要特殊处理 111 switch runes[i] { 112 case 'j': 113 for _, s := range []string{"=j=0", "=j="} { 114 result = strings.Replace(result, s, "", -1) 115 } 116 buffer.WriteString(result) 117 case 'G': 118 for _, s := range []string{"=G=0", "=G="} { 119 result = strings.Replace(result, s, "", -1) 120 } 121 buffer.WriteString(result) 122 case 'u': 123 buffer.WriteString(strings.Replace(result, "=u=.", "", -1)) 124 case 'w': 125 buffer.WriteString(weekMap[result]) 126 case 'N': 127 buffer.WriteString(strings.Replace(weekMap[result], "0", "7", -1)) 128 case 'S': 129 buffer.WriteString(formatMonthDaySuffixMap(result)) 130 default: 131 buffer.WriteString(result) 132 } 133 } else { 134 buffer.WriteRune(runes[i]) 135 } 136 } 137 i++ 138 } 139 return buffer.String() 140 } 141 142 // 通过自定义格式转换当前日期为新的日期。 143 func (t *Time) FormatTo(format string) *Time { 144 t.Time = NewFromStr(t.Format(format)).Time 145 return t 146 } 147 148 // 使用标准库格式格式化输出日期。 149 func (t *Time) Layout(layout string) string { 150 return t.Time.Format(layout) 151 } 152 153 // 通过标准库格式转换当前日期为新的日期。 154 func (t *Time) LayoutTo(layout string) *Time { 155 t.Time = NewFromStr(t.Layout(layout)).Time 156 return t 157 } 158 159 // 返回是否是润年 160 func (t *Time) IsLeapYear() bool { 161 year := t.Year() 162 if (year%4 == 0 && year%100 != 0) || year%400 == 0 { 163 return true 164 } 165 return false 166 } 167 168 // 返回一个时间点在当年中是第几天 0到365 有润年情况 169 func (t *Time) DayOfYear() int { 170 month := int(t.Month()) 171 day := t.Day() 172 173 // 判断是否润年 174 if t.IsLeapYear() { 175 if month > 2 { 176 return dayOfMonth[month-1] + day 177 } 178 return dayOfMonth[month-1] + day - 1 179 } 180 return dayOfMonth[month-1] + day - 1 181 } 182 183 // 一个时间点所在的月最长有多少天 28至31 184 func (t *Time) DaysInMonth() int { 185 switch t.Month() { 186 case 1, 3, 5, 7, 8, 10, 12: 187 return 31 188 case 4, 6, 9, 11: 189 return 30 190 } 191 192 // 只剩下第二月份,润年29天 193 if t.IsLeapYear() { 194 return 29 195 } 196 return 28 197 } 198 199 // 获取时间点在本年内是第多少周 200 func (t *Time) WeeksOfYear() int { 201 _, week := t.ISOWeek() 202 return week 203 } 204 205 // 将自定义的格式转换为标准库时间格式 206 func formatToStdLayout(format string) string { 207 b := bytes.NewBuffer(nil) 208 for i := 0; i < len(format); { 209 switch format[i] { 210 case '\\': 211 if i < len(format)-1 { 212 b.WriteByte(format[i+1]) 213 i += 2 214 continue 215 } else { 216 return b.String() 217 } 218 219 default: 220 if f, ok := formats[format[i]]; ok { 221 // 有几个转换的符号需要特殊处理 222 switch format[i] { 223 case 'j': 224 b.WriteString("02") 225 case 'G': 226 b.WriteString("15") 227 case 'u': 228 if i > 0 && format[i-1] == '.' { 229 b.WriteString("000") 230 } else { 231 b.WriteString(".000") 232 } 233 234 default: 235 b.WriteString(f) 236 } 237 } else { 238 b.WriteByte(format[i]) 239 } 240 i++ 241 } 242 } 243 return b.String() 244 } 245 246 // 将format格式转换为正则表达式规则 247 func formatToRegexPattern(format string) string { 248 s := gregex.Quote(formatToStdLayout(format)) 249 s, _ = gregex.ReplaceString(`[0-9]`, `[0-9]`, s) 250 s, _ = gregex.ReplaceString(`[A-Za-z]`, `[A-Za-z]`, s) 251 return s 252 } 253 254 // 每月天数后面的英文后缀,2 个字符st nd,rd 或者 th 255 func formatMonthDaySuffixMap(day string) string { 256 switch day { 257 case "01": 258 return "st" 259 case "02": 260 return "nd" 261 case "03": 262 return "rd" 263 default: 264 return "th" 265 } 266 }