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) }