mirror of
https://github.com/golang/go
synced 2024-10-06 15:21:23 -06:00
228 lines
4.3 KiB
Go
228 lines
4.3 KiB
Go
|
package time
|
||
|
|
||
|
import (
|
||
|
"strconv"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
numeric = iota
|
||
|
alphabetic
|
||
|
separator
|
||
|
)
|
||
|
|
||
|
// These are predefined layouts for use in Time.Format.
|
||
|
// The standard time used in the layouts is:
|
||
|
// Mon Jan 2 15:04:05 PST 2006 (PST is GMT-0800)
|
||
|
// which is Unix time 1136243045.
|
||
|
const (
|
||
|
ANSIC = "Mon Jan 2 15:04:05 2006"
|
||
|
UnixDate = "Mon Jan 2 15:04:05 PST 2006"
|
||
|
RFC850 = "Monday, 02-Jan-06 15:04:05 PST"
|
||
|
RFC1123 = "Mon, 02 Jan 2006 15:04:05 PST"
|
||
|
Kitchen = "3:04PM"
|
||
|
// Special case: use Z to get the time zone formatted according to ISO 8601,
|
||
|
// which is -0800 or Z for UTC
|
||
|
ISO8601 = "2006-01-02T15:04:05Z"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
stdLongMonth = "January"
|
||
|
stdMonth = "Jan"
|
||
|
stdNumMonth = "1"
|
||
|
stdZeroMonth = "01"
|
||
|
stdLongWeekDay = "Monday"
|
||
|
stdWeekDay = "Mon"
|
||
|
stdDay = "2"
|
||
|
stdZeroDay = "02"
|
||
|
stdHour = "15"
|
||
|
stdHour12 = "3"
|
||
|
stdZeroHour12 = "03"
|
||
|
stdMinute = "4"
|
||
|
stdZeroMinute = "04"
|
||
|
stdSecond = "5"
|
||
|
stdZeroSecond = "05"
|
||
|
stdLongYear = "2006"
|
||
|
stdYear = "06"
|
||
|
stdZulu = "1504"
|
||
|
stdPM = "PM"
|
||
|
stdpm = "pm"
|
||
|
stdTZ = "PST"
|
||
|
stdISO8601TZ = "Z"
|
||
|
)
|
||
|
|
||
|
var longDayNames = []string{
|
||
|
"Sunday",
|
||
|
"Monday",
|
||
|
"Tuesday",
|
||
|
"Wednesday",
|
||
|
"Thursday",
|
||
|
"Friday",
|
||
|
"Saturday",
|
||
|
}
|
||
|
|
||
|
var shortDayNames = []string{
|
||
|
"Sun",
|
||
|
"Mon",
|
||
|
"Tue",
|
||
|
"Wed",
|
||
|
"Thu",
|
||
|
"Fri",
|
||
|
"Sat",
|
||
|
}
|
||
|
|
||
|
var shortMonthNames = []string{
|
||
|
"---",
|
||
|
"Jan",
|
||
|
"Feb",
|
||
|
"Mar",
|
||
|
"Apr",
|
||
|
"May",
|
||
|
"Jun",
|
||
|
"Jul",
|
||
|
"Aug",
|
||
|
"Sep",
|
||
|
"Oct",
|
||
|
"Nov",
|
||
|
"Dec",
|
||
|
}
|
||
|
|
||
|
var longMonthNames = []string{
|
||
|
"---",
|
||
|
"January",
|
||
|
"February",
|
||
|
"March",
|
||
|
"April",
|
||
|
"May",
|
||
|
"June",
|
||
|
"July",
|
||
|
"August",
|
||
|
"September",
|
||
|
"October",
|
||
|
"November",
|
||
|
"December",
|
||
|
}
|
||
|
|
||
|
func charType(c uint8) int {
|
||
|
switch {
|
||
|
case '0' <= c && c <= '9':
|
||
|
return numeric
|
||
|
case 'a' <= c && c < 'z', 'A' <= c && c <= 'Z':
|
||
|
return alphabetic
|
||
|
}
|
||
|
return separator
|
||
|
}
|
||
|
|
||
|
func pieces(s string) []string {
|
||
|
p := make([]string, 20)
|
||
|
i := 0
|
||
|
// Each iteration generates one piece
|
||
|
for n := range p {
|
||
|
if i >= len(s) {
|
||
|
p = p[0:n]
|
||
|
break
|
||
|
}
|
||
|
start := i
|
||
|
c := s[i]
|
||
|
pieceType := charType(c)
|
||
|
for i < len(s) && charType(s[i]) == pieceType {
|
||
|
i++
|
||
|
}
|
||
|
p[n] = s[start:i]
|
||
|
}
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func zeroPad(i int) string {
|
||
|
s := strconv.Itoa(i)
|
||
|
if i < 10 {
|
||
|
s = "0" + s
|
||
|
}
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
// Format returns a textual representation of the time value formatted
|
||
|
// according to layout. The layout defines the format by showing the
|
||
|
// representation of a standard time, which is then used to describe
|
||
|
// the time to be formatted. Predefined layouts ANSIC, UnixDate,
|
||
|
// ISO8601 and others describe standard representations.
|
||
|
func (t *Time) Format(layout string) string {
|
||
|
pc := pieces(layout)
|
||
|
s := ""
|
||
|
for _, p := range pc {
|
||
|
switch p {
|
||
|
case stdYear:
|
||
|
p = strconv.Itoa64(t.Year % 100)
|
||
|
case stdLongYear:
|
||
|
p = strconv.Itoa64(t.Year)
|
||
|
case stdMonth:
|
||
|
p = shortMonthNames[t.Month]
|
||
|
case stdLongMonth:
|
||
|
p = longMonthNames[t.Month]
|
||
|
case stdNumMonth:
|
||
|
p = strconv.Itoa(t.Month)
|
||
|
case stdZeroMonth:
|
||
|
p = zeroPad(t.Month)
|
||
|
case stdWeekDay:
|
||
|
p = shortDayNames[t.Weekday]
|
||
|
case stdLongWeekDay:
|
||
|
p = longDayNames[t.Weekday]
|
||
|
case stdDay:
|
||
|
p = strconv.Itoa(t.Day)
|
||
|
case stdZeroDay:
|
||
|
p = zeroPad(t.Day)
|
||
|
case stdHour:
|
||
|
p = zeroPad(t.Hour)
|
||
|
case stdHour12:
|
||
|
p = strconv.Itoa(t.Hour % 12)
|
||
|
case stdZeroHour12:
|
||
|
p = zeroPad(t.Hour % 12)
|
||
|
case stdMinute:
|
||
|
p = strconv.Itoa(t.Minute)
|
||
|
case stdZeroMinute:
|
||
|
p = zeroPad(t.Minute)
|
||
|
case stdSecond:
|
||
|
p = strconv.Itoa(t.Second)
|
||
|
case stdZeroSecond:
|
||
|
p = zeroPad(t.Second)
|
||
|
case stdZulu:
|
||
|
p = zeroPad(t.Hour) + zeroPad(t.Minute)
|
||
|
case stdISO8601TZ:
|
||
|
// Rather ugly special case, required because the time zone is too broken down
|
||
|
// in this format to recognize easily. We cheat and take "Z" to mean "the time
|
||
|
// zone as formatted for ISO 8601".
|
||
|
if t.ZoneOffset == 0 {
|
||
|
p = "Z"
|
||
|
} else {
|
||
|
zone := t.ZoneOffset / 60 // minutes
|
||
|
if zone < 0 {
|
||
|
p = "-"
|
||
|
zone = -zone
|
||
|
} else {
|
||
|
p = "+"
|
||
|
}
|
||
|
p += zeroPad(zone / 60)
|
||
|
p += zeroPad(zone % 60)
|
||
|
}
|
||
|
case stdPM:
|
||
|
if t.Hour >= 12 {
|
||
|
p = "PM"
|
||
|
} else {
|
||
|
p = "AM"
|
||
|
}
|
||
|
case stdpm:
|
||
|
if t.Hour >= 12 {
|
||
|
p = "pm"
|
||
|
} else {
|
||
|
p = "am"
|
||
|
}
|
||
|
case stdTZ:
|
||
|
p = t.Zone
|
||
|
}
|
||
|
s += p
|
||
|
}
|
||
|
return s
|
||
|
}
|
||
|
|
||
|
// String returns a Unix-style representation of the time value.
|
||
|
func (t *Time) String() string { return t.Format(UnixDate) }
|