diff --git a/os/gtime/gtime_format.go b/os/gtime/gtime_format.go index 4540249b7..dbc3252fb 100644 --- a/os/gtime/gtime_format.go +++ b/os/gtime/gtime_format.go @@ -15,55 +15,55 @@ import ( ) var ( - // Please refer: http://php.net/manual/zh/function.date.php + // Please refer: http://php.net/manual/en/function.date.php formats = map[byte]string{ // ================== Day ================== 'd': "02", // Day of the month, 2 digits with leading zeros. Eg: 01 to 31 'D': "Mon", // A textual representation of a day, three letters. Eg: Mon through Sun - 'w': "Monday", // 星期中的第几天,数字型式的文本表示 0为星期天 6为星期六 - 'N': "Monday", // ISO-8601 格式数字表示的星期中的第几天 1(表示星期一)到 7(表示星期天) - 'j': "=j=02", // 月份中的第几天,没有前导零(1 到 31) - 'S': "02", // 每月天数后面的英文后缀,2 个字符 st,nd,rd 或者 th。可以和 j 一起用 - 'l': "Monday", // ("L"的小写字母)星期几,完整的文本格式(Sunday 到 Saturday) - 'z': "", // 年份中的第几天 0到365 + 'w': "Monday", // Numeric representation of the day of the week. Eg: 0 (for Sunday) through 6 (for Saturday) + 'N': "Monday", // ISO-8601 numeric representation of the day of the week. Eg: 1 (for Monday) through 7 (for Sunday) + 'j': "=j=02", // Day of the month without leading zeros. Eg: 1 to 31 + 'S': "02", // English ordinal suffix for the day of the month, 2 characters. Eg: st, nd, rd or th. Works well with j + 'l': "Monday", // A full textual representation of the day of the week. Eg: Sunday through Saturday + 'z': "", // The day of the year (starting from 0). Eg: 0 through 365 // ================== Week ================== - 'W': "", // ISO-8601 格式年份中的第几周,每周从星期一开始 例如:42(当年的第 42 周) + 'W': "", // ISO-8601 week number of year, weeks starting on Monday. Eg: 42 (the 42nd week in the year) // ================== Month ================== - 'F': "January", // 月份,完整的文本格式,例如 January 或者 March January 到 December - 'm': "01", // 数字表示的月份,有前导零(01 到 12) - 'M': "Jan", // 三个字母缩写表示的月份(Jan 到 Dec) - 'n': "1", // 数字表示的月份,没有前导零(1 到 12) - 't': "", // 指定的月份有几天 28到31 + 'F': "January", // A full textual representation of a month, such as January or March. Eg: January through December + 'm': "01", // Numeric representation of a month, with leading zeros. Eg: 01 through 12 + 'M': "Jan", // A short textual representation of a month, three letters. Eg: Jan through Dec + 'n': "1", // Numeric representation of a month, without leading zeros. Eg: 1 through 12 + 't': "", // Number of days in the given month. Eg: 28 through 31 // ================== Year ================== - 'Y': "2006", // 4 位数字完整表示的年份, 例如:1999 或 2003 - 'y': "06", // 2 位数字表示的年份, 例如:99 或 03 + 'Y': "2006", // A full numeric representation of a year, 4 digits. Eg: 1999 or 2003 + 'y': "06", // A two digit representation of a year. Eg: 99 or 03 // ================== Time ================== - 'a': "pm", // 小写的上午和下午值 am 或 pm - 'A': "PM", // 大写的上午和下午值 AM 或 PM - 'g': "3", // 小时,12 小时格式,没有前导零, 1 到 12 - 'G': "=G=15", // 小时,24 小时格式,没有前导零, 0 到 23 - 'h': "03", // 小时,12 小时格式,有前导零, 01 到 12 - 'H': "15", // 小时,24 小时格式,有前导零, 00 到 23 - 'i': "04", // 有前导零的分钟数, 00 到 59 - 's': "05", // 秒数,有前导零, 00 到 59 - 'u': "=u=.000", // 毫秒(3位) - 'U': "", // 将时间格式化为Unix时间,即从时间点January 1, 1970 UTC到时间点t所经过的时间(单位秒) + 'a': "pm", // Lowercase Ante meridiem and Post meridiem. Eg: am or pm + 'A': "PM", // Uppercase Ante meridiem and Post meridiem. Eg: AM or PM + 'g': "3", // 12-hour format of an hour without leading zeros. Eg: 1 through 12 + 'G': "=G=15", // 24-hour format of an hour without leading zeros. Eg: 0 through 23 + 'h': "03", // 12-hour format of an hour with leading zeros. Eg: 01 through 12 + 'H': "15", // 24-hour format of an hour with leading zeros. Eg: 00 through 23 + 'i': "04", // Minutes with leading zeros. Eg: 00 to 59 + 's': "05", // Seconds with leading zeros. Eg: 00 through 59 + 'u': "=u=.000", // Milliseconds. Eg: 234, 678 + 'U': "", // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). // ================== Zone ================== - 'O': "-0700", // 与UTC相差的小时数, 例如:+0200 - 'P': "-07:00", // 与UTC的差别,小时和分钟之间有冒号分隔, 例如:+02:00 - 'T': "MST", // 时区缩写, 例如: UTC, EST, MDT + 'O': "-0700", // Difference to Greenwich time (GMT) in hours. Eg: +0200 + 'P': "-07:00", // Difference to Greenwich time (GMT) with colon between hours and minutes. Eg: +02:00 + 'T': "MST", // Timezone abbreviation. Eg: UTC, EST, MDT ... // ================== Format ================== - 'c': "2006-01-02T15:04:05-07:00", // ISO 8601 格式的日期,例如:2004-02-12T15:19:21+00:00 - 'r': "Mon, 02 Jan 06 15:04 MST", // RFC 822 格式的日期,例如:Thu, 21 Dec 2000 16:01:07 +0200 + 'c': "2006-01-02T15:04:05-07:00", // ISO 8601 date. Eg: 2004-02-12T15:19:21+00:00 + 'r': "Mon, 02 Jan 06 15:04 MST", // RFC 2822 formatted date. Eg: Thu, 21 Dec 2000 16:01:07 +0200 } - // 星期的英文值和数字值对应map + // Week to number mapping. weekMap = map[string]string{ "Sunday": "0", "Monday": "1", @@ -74,11 +74,11 @@ var ( "Saturday": "6", } - // 每个月累计的天数 不含润年的时候 + // Day count of each month which is not in leap year. dayOfMonth = []int{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334} ) -// 使用自定义日期格式格式化输出日期。 +// Format formats and returns the formatted result with custom . func (t *Time) Format(format string) string { runes := []rune(format) buffer := bytes.NewBuffer(nil) @@ -107,7 +107,7 @@ func (t *Time) Format(format string) string { } if f, ok := formats[byte(runes[i])]; ok { result := t.Time.Format(f) - // 有几个转换的符号需要特殊处理 + // Particular chars should be handled here. switch runes[i] { case 'j': for _, s := range []string{"=j=0", "=j="} { @@ -139,24 +139,24 @@ func (t *Time) Format(format string) string { return buffer.String() } -// 通过自定义格式转换当前日期为新的日期。 +// FormatTo formats and returns a new Time object with given custom . func (t *Time) FormatTo(format string) *Time { t.Time = NewFromStr(t.Format(format)).Time return t } -// 使用标准库格式格式化输出日期。 +// Layout formats the time with stdlib layout and returns the formatted result. func (t *Time) Layout(layout string) string { return t.Time.Format(layout) } -// 通过标准库格式转换当前日期为新的日期。 +// Layout formats the time with stdlib layout and returns the new Time object. func (t *Time) LayoutTo(layout string) *Time { t.Time = NewFromStr(t.Layout(layout)).Time return t } -// 返回是否是润年 +// IsLeapYear checks whether the time is leap year. func (t *Time) IsLeapYear() bool { year := t.Year() if (year%4 == 0 && year%100 != 0) || year%400 == 0 { @@ -165,12 +165,10 @@ func (t *Time) IsLeapYear() bool { return false } -// 返回一个时间点在当年中是第几天 0到365 有润年情况 +// DayOfYear checks and returns the position of the day for the year. func (t *Time) DayOfYear() int { - month := int(t.Month()) day := t.Day() - - // 判断是否润年 + month := int(t.Month()) if t.IsLeapYear() { if month > 2 { return dayOfMonth[month-1] + day @@ -180,7 +178,7 @@ func (t *Time) DayOfYear() int { return dayOfMonth[month-1] + day - 1 } -// 一个时间点所在的月最长有多少天 28至31 +// DaysInMonth returns the day count of current month. func (t *Time) DaysInMonth() int { switch t.Month() { case 1, 3, 5, 7, 8, 10, 12: @@ -188,21 +186,19 @@ func (t *Time) DaysInMonth() int { case 4, 6, 9, 11: return 30 } - - // 只剩下第二月份,润年29天 if t.IsLeapYear() { return 29 } return 28 } -// 获取时间点在本年内是第多少周 +// WeeksOfYear returns the point of current week for the year. func (t *Time) WeeksOfYear() int { _, week := t.ISOWeek() return week } -// 将自定义的格式转换为标准库时间格式 +// formatToStdLayout converts custom format to stdlib layout. func formatToStdLayout(format string) string { b := bytes.NewBuffer(nil) for i := 0; i < len(format); { @@ -243,7 +239,7 @@ func formatToStdLayout(format string) string { return b.String() } -// 将format格式转换为正则表达式规则 +// formatToRegexPattern converts the custom format to its corresponding regular expression. func formatToRegexPattern(format string) string { s := gregex.Quote(formatToStdLayout(format)) s, _ = gregex.ReplaceString(`[0-9]`, `[0-9]`, s) @@ -251,7 +247,7 @@ func formatToRegexPattern(format string) string { return s } -// 每月天数后面的英文后缀,2 个字符st nd,rd 或者 th +// formatMonthDaySuffixMap returns the short english word for current day. func formatMonthDaySuffixMap(day string) string { switch day { case "01": diff --git a/os/gtime/gtime_time.go b/os/gtime/gtime_time.go index 59fca22a4..cfe82bb43 100644 --- a/os/gtime/gtime_time.go +++ b/os/gtime/gtime_time.go @@ -7,14 +7,18 @@ package gtime import ( + "bytes" + "github.com/gogf/gf/util/gconv" "time" ) +// Time is a wrapper for time.Time for additional features. type Time struct { time.Time } -// 创建一个空的时间对象,参数可以是标准库时间对象,可选 +// New creates and returns a Time object with given time.Time object. +// The parameter is optional. func New(t ...time.Time) *Time { if len(t) > 0 { return NewFromTime(t[0]) @@ -24,21 +28,21 @@ func New(t ...time.Time) *Time { } } -// 当前时间对象 +// Now returns a time object for now. func Now() *Time { return &Time{ time.Now(), } } -// 标准时间对象转换为自定义的时间对象 +// NewFromTime creates and returns a Time object with given time.Time object. func NewFromTime(t time.Time) *Time { return &Time{ t, } } -// 从字符串转换为时间对象,复杂的时间字符串需要给定格式 +// NewFromStr creates and returns a Time object with given string. func NewFromStr(str string) *Time { if t, err := StrToTime(str); err == nil { return t @@ -46,7 +50,7 @@ func NewFromStr(str string) *Time { return nil } -// 从字符串转换为时间对象,指定字符串时间格式,format格式形如:Y-m-d H:i:s +// NewFromStrFormat creates and returns a Time object with given string and custom format like: Y-m-d H:i:s. func NewFromStrFormat(str string, format string) *Time { if t, err := StrToTimeFormat(str, format); err == nil { return t @@ -54,7 +58,7 @@ func NewFromStrFormat(str string, format string) *Time { return nil } -// 从字符串转换为时间对象,通过标准库layout格式进行解析,layout格式形如:2006-01-02 15:04:05 +// NewFromStrLayout creates and returns a Time object with given string and stdlib layout like: 2006-01-02 15:04:05. func NewFromStrLayout(str string, layout string) *Time { if t, err := StrToTimeLayout(str, layout); err == nil { return t @@ -62,7 +66,7 @@ func NewFromStrLayout(str string, layout string) *Time { return nil } -// 时间戳转换为时间对象,时间戳支持到纳秒的数值 +// NewFromTimeStamp creates and returns a Time object with given timestamp, which can be in seconds to nanoseconds. func NewFromTimeStamp(timestamp int64) *Time { if timestamp == 0 { return &Time{} @@ -71,47 +75,47 @@ func NewFromTimeStamp(timestamp int64) *Time { timestamp *= 10 } return &Time{ - time.Unix(int64(timestamp/1e9), timestamp%1e9), + time.Unix(timestamp/1e9, timestamp%1e9), } } -// 秒数(时间戳) +// Second returns the timestamp in seconds. func (t *Time) Second() int64 { return t.UnixNano() / 1e9 } -// 纳秒数 +// Nanosecond returns the timestamp in nanoseconds. func (t *Time) Nanosecond() int64 { return t.UnixNano() } -// 微秒数 +// Microsecond returns the timestamp in microseconds. func (t *Time) Microsecond() int64 { return t.UnixNano() / 1e3 } -// 毫秒数 +// Millisecond returns the timestamp in milliseconds. func (t *Time) Millisecond() int64 { return t.UnixNano() / 1e6 } -// 转换为字符串 +// String returns current time object as string. func (t *Time) String() string { return t.Format("Y-m-d H:i:s") } -// 复制当前时间对象 +// Clone returns a new Time object which is a clone of current time object. func (t *Time) Clone() *Time { return New(t.Time) } -// 当前时间加上指定时间段 +// Add adds the duration to current time. func (t *Time) Add(d time.Duration) *Time { t.Time = t.Time.Add(d) return t } -// 当前时间加上指定时间段(使用字符串格式) +// AddStr parses the given duration as string and adds it to current time. func (t *Time) AddStr(duration string) error { if d, err := time.ParseDuration(duration); err != nil { return err @@ -121,13 +125,13 @@ func (t *Time) AddStr(duration string) error { return nil } -// 时区转换为指定的时区(通过time.Location) +// ToLocation converts current time to specified location. func (t *Time) ToLocation(location *time.Location) *Time { t.Time = t.Time.In(location) return t } -// 时区转换为指定的时区(通过时区名称,如:Asia/Shanghai) +// ToZone converts current time to specified zone like: Asia/Shanghai. func (t *Time) ToZone(zone string) (*Time, error) { if l, err := time.LoadLocation(zone); err == nil { t.Time = t.Time.In(l) @@ -137,46 +141,54 @@ func (t *Time) ToZone(zone string) (*Time, error) { } } -// 时区转换为UTC时区 +// UTC converts current time to UTC timezone. func (t *Time) UTC() *Time { t.Time = t.Time.UTC() return t } -// 时间输出为ISO8601格式 +// ISO8601 formats the time as ISO8601 and returns it as string. func (t *Time) ISO8601() string { return t.Layout("2006-01-02T15:04:05-07:00") } -// 时间输出为RFC822格式 +// RFC822 formats the time as RFC822 and returns it as string. func (t *Time) RFC822() string { return t.Layout("Mon, 02 Jan 06 15:04 MST") } -// 时区转换为当前设定的Local时区 +// Local converts the time to local timezone. func (t *Time) Local() *Time { t.Time = t.Time.Local() return t } -// 时间日期计算 +// AddDate adds year, month and day to the time. func (t *Time) AddDate(years int, months int, days int) *Time { t.Time = t.Time.AddDate(years, months, days) return t } -// Round将舍入t的结果返回到d的最接近的倍数(从零时间开始)。 -// 中间值的舍入行为是向上舍入。 如果d <= 0,Round返回t剥离任何单调时钟读数但不改变。 -// Round作为零时间以来的绝对持续时间运行; 它不适用于当时的演示形式。 -// 因此,Round(Hour)可能会返回非零分钟的时间,具体取决于时间的位置。 +// Round returns the result of rounding t to the nearest multiple of d (since the zero time). +// The rounding behavior for halfway values is to round up. +// If d <= 0, Round returns t stripped of any monotonic clock reading but otherwise unchanged. +// +// Round operates on the time as an absolute duration since the +// zero time; it does not operate on the presentation form of the +// time. Thus, Round(Hour) may return a time with a non-zero +// minute, depending on the time's Location. func (t *Time) Round(d time.Duration) *Time { t.Time = t.Time.Round(d) return t } -// Truncate将舍入t的结果返回到d的倍数(从零时间开始)。 如果d <= 0,则Truncate返回t剥离任何单调时钟读数但不改变。 -// 截断时间作为零时间以来的绝对持续时间运行; 它不适用于当时的演示形式。 -// 因此,截断(小时)可能会返回非零分钟的时间,具体取决于时间的位置。 +// Truncate returns the result of rounding t down to a multiple of d (since the zero time). +// If d <= 0, Truncate returns t stripped of any monotonic clock reading but otherwise unchanged. +// +// Truncate operates on the time as an absolute duration since the +// zero time; it does not operate on the presentation form of the +// time. Thus, Truncate(Hour) may return a time with a non-zero +// minute, depending on the time's Location. func (t *Time) Truncate(d time.Duration) *Time { t.Time = t.Time.Truncate(d) return t @@ -184,5 +196,15 @@ func (t *Time) Truncate(d time.Duration) *Time { // MarshalJSON implements the interface MarshalJSON for json.Marshal. func (t *Time) MarshalJSON() ([]byte, error) { - return []byte(`"` + t.String() + `"`), nil + return gconv.UnsafeStrToBytes(`"` + t.String() + `"`), nil +} + +// UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. +func (t *Time) UnmarshalJSON(b []byte) error { + newTime, err := StrToTime(gconv.UnsafeBytesToStr(bytes.Trim(b, `"`))) + if err != nil { + return err + } + t.Time = newTime.Time + return nil }