1
0
mirror of https://github.com/golang/go synced 2024-10-06 15:31:22 -06:00
go/src/pkg/time/format.go

218 lines
4.2 KiB
Go
Raw Normal View History

package time
import (
"bytes"
"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 MST 2006 (MST is GMT-0700)
// which is Unix time 1136243045.
// (Think of it as 01/02 03:04:05PM '06 -0700.)
const (
ANSIC = "Mon Jan 2 15:04:05 2006"
UnixDate = "Mon Jan 2 15:04:05 MST 2006"
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
Kitchen = "3:04PM"
// Special case: use Z to get the time zone formatted according to ISO 8601,
// which is -0700 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 = "MST"
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 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 {
b := new(bytes.Buffer)
// Each iteration generates one piece
for len(layout) > 0 {
c := layout[0]
pieceType := charType(c)
i := 0
for i < len(layout) && charType(layout[i]) == pieceType {
i++
}
p := layout[0:i]
layout = layout[i:]
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
}
b.WriteString(p)
}
return b.String()
}
// String returns a Unix-style representation of the time value.
func (t *Time) String() string { return t.Format(UnixDate) }