1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249 |
- package time
- import "errors"
- const (
- ANSIC = "Mon Jan _2 15:04:05 2006"
- UnixDate = "Mon Jan _2 15:04:05 MST 2006"
- RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
- RFC822 = "02 Jan 06 15:04 MST"
- RFC822Z = "02 Jan 06 15:04 -0700"
- RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
- RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
- RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700"
- RFC3339 = "2006-01-02T15:04:05Z07:00"
- RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
- Kitchen = "3:04PM"
-
- Stamp = "Jan _2 15:04:05"
- StampMilli = "Jan _2 15:04:05.000"
- StampMicro = "Jan _2 15:04:05.000000"
- StampNano = "Jan _2 15:04:05.000000000"
- )
- const (
- _ = iota
- stdLongMonth = iota + stdNeedDate
- stdMonth
- stdNumMonth
- stdZeroMonth
- stdLongWeekDay
- stdWeekDay
- stdDay
- stdUnderDay
- stdZeroDay
- stdHour = iota + stdNeedClock
- stdHour12
- stdZeroHour12
- stdMinute
- stdZeroMinute
- stdSecond
- stdZeroSecond
- stdLongYear = iota + stdNeedDate
- stdYear
- stdPM = iota + stdNeedClock
- stdpm
- stdTZ = iota
- stdISO8601TZ
- stdISO8601SecondsTZ
- stdISO8601ColonTZ
- stdISO8601ColonSecondsTZ
- stdNumTZ
- stdNumSecondsTz
- stdNumShortTZ
- stdNumColonTZ
- stdNumColonSecondsTZ
- stdFracSecond0
- stdFracSecond9
- stdNeedDate = 1 << 8
- stdNeedClock = 2 << 8
- stdArgShift = 16
- stdMask = 1<<stdArgShift - 1
- )
- var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
- func startsWithLowerCase(str string) bool {
- if len(str) == 0 {
- return false
- }
- c := str[0]
- return 'a' <= c && c <= 'z'
- }
- func nextStdChunk(layout string) (prefix string, std int, suffix string) {
- for i := 0; i < len(layout); i++ {
- switch c := int(layout[i]); c {
- case 'J':
- if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
- if len(layout) >= i+7 && layout[i:i+7] == "January" {
- return layout[0:i], stdLongMonth, layout[i+7:]
- }
- if !startsWithLowerCase(layout[i+3:]) {
- return layout[0:i], stdMonth, layout[i+3:]
- }
- }
- case 'M':
- if len(layout) >= i+3 {
- if layout[i:i+3] == "Mon" {
- if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
- return layout[0:i], stdLongWeekDay, layout[i+6:]
- }
- if !startsWithLowerCase(layout[i+3:]) {
- return layout[0:i], stdWeekDay, layout[i+3:]
- }
- }
- if layout[i:i+3] == "MST" {
- return layout[0:i], stdTZ, layout[i+3:]
- }
- }
- case '0':
- if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
- return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
- }
- case '1':
- if len(layout) >= i+2 && layout[i+1] == '5' {
- return layout[0:i], stdHour, layout[i+2:]
- }
- return layout[0:i], stdNumMonth, layout[i+1:]
- case '2':
- if len(layout) >= i+4 && layout[i:i+4] == "2006" {
- return layout[0:i], stdLongYear, layout[i+4:]
- }
- return layout[0:i], stdDay, layout[i+1:]
- case '_':
- if len(layout) >= i+2 && layout[i+1] == '2' {
- return layout[0:i], stdUnderDay, layout[i+2:]
- }
- case '3':
- return layout[0:i], stdHour12, layout[i+1:]
- case '4':
- return layout[0:i], stdMinute, layout[i+1:]
- case '5':
- return layout[0:i], stdSecond, layout[i+1:]
- case 'P':
- if len(layout) >= i+2 && layout[i+1] == 'M' {
- return layout[0:i], stdPM, layout[i+2:]
- }
- case 'p':
- if len(layout) >= i+2 && layout[i+1] == 'm' {
- return layout[0:i], stdpm, layout[i+2:]
- }
- case '-':
- if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
- return layout[0:i], stdNumSecondsTz, layout[i+7:]
- }
- if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
- return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
- }
- if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
- return layout[0:i], stdNumTZ, layout[i+5:]
- }
- if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
- return layout[0:i], stdNumColonTZ, layout[i+6:]
- }
- if len(layout) >= i+3 && layout[i:i+3] == "-07" {
- return layout[0:i], stdNumShortTZ, layout[i+3:]
- }
- case 'Z':
- if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
- return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
- }
- if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
- return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
- }
- if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
- return layout[0:i], stdISO8601TZ, layout[i+5:]
- }
- if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
- return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
- }
- case '.':
- if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
- ch := layout[i+1]
- j := i + 1
- for j < len(layout) && layout[j] == ch {
- j++
- }
-
- if !isDigit(layout, j) {
- std := stdFracSecond0
- if layout[i+1] == '9' {
- std = stdFracSecond9
- }
- std |= (j - (i + 1)) << stdArgShift
- return layout[0:i], std, layout[j:]
- }
- }
- }
- }
- return layout, 0, ""
- }
- 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 match(s1, s2 string) bool {
- for i := 0; i < len(s1); i++ {
- c1 := s1[i]
- c2 := s2[i]
- if c1 != c2 {
-
- c1 |= 'a' - 'A'
- c2 |= 'a' - 'A'
- if c1 != c2 || c1 < 'a' || c1 > 'z' {
- return false
- }
- }
- }
- return true
- }
- func lookup(tab []string, val string) (int, string, error) {
- for i, v := range tab {
- if len(val) >= len(v) && match(val[0:len(v)], v) {
- return i, val[len(v):], nil
- }
- }
- return -1, val, errBad
- }
- func appendUint(b []byte, x uint, pad byte) []byte {
- if x < 10 {
- if pad != 0 {
- b = append(b, pad)
- }
- return append(b, byte('0'+x))
- }
- if x < 100 {
- b = append(b, byte('0'+x/10))
- b = append(b, byte('0'+x%10))
- return b
- }
- var buf [32]byte
- n := len(buf)
- if x == 0 {
- return append(b, '0')
- }
- for x >= 10 {
- n--
- buf[n] = byte(x%10 + '0')
- x /= 10
- }
- n--
- buf[n] = byte(x + '0')
- return append(b, buf[n:]...)
- }
- var atoiError = errors.New("time: invalid number")
- func atoi(s string) (x int, err error) {
- neg := false
- if s != "" && (s[0] == '-' || s[0] == '+') {
- neg = s[0] == '-'
- s = s[1:]
- }
- q, rem, err := leadingInt(s)
- x = int(q)
- if err != nil || rem != "" {
- return 0, atoiError
- }
- if neg {
- x = -x
- }
- return x, nil
- }
- func formatNano(b []byte, nanosec uint, n int, trim bool) []byte {
- u := nanosec
- var buf [9]byte
- for start := len(buf); start > 0; {
- start--
- buf[start] = byte(u%10 + '0')
- u /= 10
- }
- if n > 9 {
- n = 9
- }
- if trim {
- for n > 0 && buf[n-1] == '0' {
- n--
- }
- if n == 0 {
- return b
- }
- }
- b = append(b, '.')
- return append(b, buf[:n]...)
- }
- func (t Time) String() string {
- return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
- }
- func (t Time) Format(layout string) string {
- var (
- name, offset, abs = t.locabs()
- year int = -1
- month Month
- day int
- hour int = -1
- min int
- sec int
- b []byte
- buf [64]byte
- )
- max := len(layout) + 10
- if max <= len(buf) {
- b = buf[:0]
- } else {
- b = make([]byte, 0, max)
- }
-
- for layout != "" {
- prefix, std, suffix := nextStdChunk(layout)
- if prefix != "" {
- b = append(b, prefix...)
- }
- if std == 0 {
- break
- }
- layout = suffix
-
- if year < 0 && std&stdNeedDate != 0 {
- year, month, day, _ = absDate(abs, true)
- }
-
- if hour < 0 && std&stdNeedClock != 0 {
- hour, min, sec = absClock(abs)
- }
- switch std & stdMask {
- case stdYear:
- y := year
- if y < 0 {
- y = -y
- }
- b = appendUint(b, uint(y%100), '0')
- case stdLongYear:
-
- y := year
- switch {
- case year <= -1000:
- b = append(b, '-')
- y = -y
- case year <= -100:
- b = append(b, "-0"...)
- y = -y
- case year <= -10:
- b = append(b, "-00"...)
- y = -y
- case year < 0:
- b = append(b, "-000"...)
- y = -y
- case year < 10:
- b = append(b, "000"...)
- case year < 100:
- b = append(b, "00"...)
- case year < 1000:
- b = append(b, '0')
- }
- b = appendUint(b, uint(y), 0)
- case stdMonth:
- b = append(b, month.String()[:3]...)
- case stdLongMonth:
- m := month.String()
- b = append(b, m...)
- case stdNumMonth:
- b = appendUint(b, uint(month), 0)
- case stdZeroMonth:
- b = appendUint(b, uint(month), '0')
- case stdWeekDay:
- b = append(b, absWeekday(abs).String()[:3]...)
- case stdLongWeekDay:
- s := absWeekday(abs).String()
- b = append(b, s...)
- case stdDay:
- b = appendUint(b, uint(day), 0)
- case stdUnderDay:
- b = appendUint(b, uint(day), ' ')
- case stdZeroDay:
- b = appendUint(b, uint(day), '0')
- case stdHour:
- b = appendUint(b, uint(hour), '0')
- case stdHour12:
-
- hr := hour % 12
- if hr == 0 {
- hr = 12
- }
- b = appendUint(b, uint(hr), 0)
- case stdZeroHour12:
-
- hr := hour % 12
- if hr == 0 {
- hr = 12
- }
- b = appendUint(b, uint(hr), '0')
- case stdMinute:
- b = appendUint(b, uint(min), 0)
- case stdZeroMinute:
- b = appendUint(b, uint(min), '0')
- case stdSecond:
- b = appendUint(b, uint(sec), 0)
- case stdZeroSecond:
- b = appendUint(b, uint(sec), '0')
- case stdPM:
- if hour >= 12 {
- b = append(b, "PM"...)
- } else {
- b = append(b, "AM"...)
- }
- case stdpm:
- if hour >= 12 {
- b = append(b, "pm"...)
- } else {
- b = append(b, "am"...)
- }
- case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
-
-
- if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ColonSecondsTZ) {
- b = append(b, 'Z')
- break
- }
- zone := offset / 60
- absoffset := offset
- if zone < 0 {
- b = append(b, '-')
- zone = -zone
- absoffset = -absoffset
- } else {
- b = append(b, '+')
- }
- b = appendUint(b, uint(zone/60), '0')
- if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
- b = append(b, ':')
- }
- b = appendUint(b, uint(zone%60), '0')
-
- if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
- if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
- b = append(b, ':')
- }
- b = appendUint(b, uint(absoffset%60), '0')
- }
- case stdTZ:
- if name != "" {
- b = append(b, name...)
- break
- }
-
-
- zone := offset / 60
- if zone < 0 {
- b = append(b, '-')
- zone = -zone
- } else {
- b = append(b, '+')
- }
- b = appendUint(b, uint(zone/60), '0')
- b = appendUint(b, uint(zone%60), '0')
- case stdFracSecond0, stdFracSecond9:
- b = formatNano(b, uint(t.Nanosecond()), std>>stdArgShift, std&stdMask == stdFracSecond9)
- }
- }
- return string(b)
- }
- var errBad = errors.New("bad value for field")
- type ParseError struct {
- Layout string
- Value string
- LayoutElem string
- ValueElem string
- Message string
- }
- func quote(s string) string {
- return "\"" + s + "\""
- }
- func (e *ParseError) Error() string {
- if e.Message == "" {
- return "parsing time " +
- quote(e.Value) + " as " +
- quote(e.Layout) + ": cannot parse " +
- quote(e.ValueElem) + " as " +
- quote(e.LayoutElem)
- }
- return "parsing time " +
- quote(e.Value) + e.Message
- }
- func isDigit(s string, i int) bool {
- if len(s) <= i {
- return false
- }
- c := s[i]
- return '0' <= c && c <= '9'
- }
- func getnum(s string, fixed bool) (int, string, error) {
- if !isDigit(s, 0) {
- return 0, s, errBad
- }
- if !isDigit(s, 1) {
- if fixed {
- return 0, s, errBad
- }
- return int(s[0] - '0'), s[1:], nil
- }
- return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
- }
- func cutspace(s string) string {
- for len(s) > 0 && s[0] == ' ' {
- s = s[1:]
- }
- return s
- }
- func skip(value, prefix string) (string, error) {
- for len(prefix) > 0 {
- if prefix[0] == ' ' {
- if len(value) > 0 && value[0] != ' ' {
- return value, errBad
- }
- prefix = cutspace(prefix)
- value = cutspace(value)
- continue
- }
- if len(value) == 0 || value[0] != prefix[0] {
- return value, errBad
- }
- prefix = prefix[1:]
- value = value[1:]
- }
- return value, nil
- }
- func Parse(layout, value string) (Time, error) {
- return parse(layout, value, UTC, Local)
- }
- func ParseInLocation(layout, value string, loc *Location) (Time, error) {
- return parse(layout, value, loc, loc)
- }
- func parse(layout, value string, defaultLocation, local *Location) (Time, error) {
- alayout, avalue := layout, value
- rangeErrString := ""
- amSet := false
- pmSet := false
-
- var (
- year int
- month int = 1
- day int = 1
- hour int
- min int
- sec int
- nsec int
- z *Location
- zoneOffset int = -1
- zoneName string
- )
-
- for {
- var err error
- prefix, std, suffix := nextStdChunk(layout)
- stdstr := layout[len(prefix) : len(layout)-len(suffix)]
- value, err = skip(value, prefix)
- if err != nil {
- return Time{}, &ParseError{alayout, avalue, prefix, value, ""}
- }
- if std == 0 {
- if len(value) != 0 {
- return Time{}, &ParseError{alayout, avalue, "", value, ": extra text: " + value}
- }
- break
- }
- layout = suffix
- var p string
- switch std & stdMask {
- case stdYear:
- if len(value) < 2 {
- err = errBad
- break
- }
- p, value = value[0:2], value[2:]
- year, err = atoi(p)
- if year >= 69 {
- year += 1900
- } else {
- year += 2000
- }
- case stdLongYear:
- if len(value) < 4 || !isDigit(value, 0) {
- err = errBad
- break
- }
- p, value = value[0:4], value[4:]
- year, err = atoi(p)
- case stdMonth:
- month, value, err = lookup(shortMonthNames, value)
- case stdLongMonth:
- month, value, err = lookup(longMonthNames, value)
- case stdNumMonth, stdZeroMonth:
- month, value, err = getnum(value, std == stdZeroMonth)
- if month <= 0 || 12 < month {
- rangeErrString = "month"
- }
- case stdWeekDay:
-
- _, value, err = lookup(shortDayNames, value)
- case stdLongWeekDay:
- _, value, err = lookup(longDayNames, value)
- case stdDay, stdUnderDay, stdZeroDay:
- if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
- value = value[1:]
- }
- day, value, err = getnum(value, std == stdZeroDay)
- if day < 0 || 31 < day {
- rangeErrString = "day"
- }
- case stdHour:
- hour, value, err = getnum(value, false)
- if hour < 0 || 24 <= hour {
- rangeErrString = "hour"
- }
- case stdHour12, stdZeroHour12:
- hour, value, err = getnum(value, std == stdZeroHour12)
- if hour < 0 || 12 < hour {
- rangeErrString = "hour"
- }
- case stdMinute, stdZeroMinute:
- min, value, err = getnum(value, std == stdZeroMinute)
- if min < 0 || 60 <= min {
- rangeErrString = "minute"
- }
- case stdSecond, stdZeroSecond:
- sec, value, err = getnum(value, std == stdZeroSecond)
- if sec < 0 || 60 <= sec {
- rangeErrString = "second"
- }
-
-
- if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
- _, std, _ = nextStdChunk(layout)
- std &= stdMask
- if std == stdFracSecond0 || std == stdFracSecond9 {
-
- break
- }
-
- n := 2
- for ; n < len(value) && isDigit(value, n); n++ {
- }
- nsec, rangeErrString, err = parseNanoseconds(value, n)
- value = value[n:]
- }
- case stdPM:
- if len(value) < 2 {
- err = errBad
- break
- }
- p, value = value[0:2], value[2:]
- switch p {
- case "PM":
- pmSet = true
- case "AM":
- amSet = true
- default:
- err = errBad
- }
- case stdpm:
- if len(value) < 2 {
- err = errBad
- break
- }
- p, value = value[0:2], value[2:]
- switch p {
- case "pm":
- pmSet = true
- case "am":
- amSet = true
- default:
- err = errBad
- }
- case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
- if (std == stdISO8601TZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' {
- value = value[1:]
- z = UTC
- break
- }
- var sign, hour, min, seconds string
- if std == stdISO8601ColonTZ || std == stdNumColonTZ {
- if len(value) < 6 {
- err = errBad
- break
- }
- if value[3] != ':' {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
- } else if std == stdNumShortTZ {
- if len(value) < 3 {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
- } else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
- if len(value) < 9 {
- err = errBad
- break
- }
- if value[3] != ':' || value[6] != ':' {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
- } else if std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
- if len(value) < 7 {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
- } else {
- if len(value) < 5 {
- err = errBad
- break
- }
- sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
- }
- var hr, mm, ss int
- hr, err = atoi(hour)
- if err == nil {
- mm, err = atoi(min)
- }
- if err == nil {
- ss, err = atoi(seconds)
- }
- zoneOffset = (hr*60+mm)*60 + ss
- switch sign[0] {
- case '+':
- case '-':
- zoneOffset = -zoneOffset
- default:
- err = errBad
- }
- case stdTZ:
-
- if len(value) >= 3 && value[0:3] == "UTC" {
- z = UTC
- value = value[3:]
- break
- }
- n, ok := parseTimeZone(value)
- if !ok {
- err = errBad
- break
- }
- zoneName, value = value[:n], value[n:]
- case stdFracSecond0:
-
-
- ndigit := 1 + (std >> stdArgShift)
- if len(value) < ndigit {
- err = errBad
- break
- }
- nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
- value = value[ndigit:]
- case stdFracSecond9:
- if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
-
- break
- }
-
-
- i := 0
- for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
- i++
- }
- nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
- value = value[1+i:]
- }
- if rangeErrString != "" {
- return Time{}, &ParseError{alayout, avalue, stdstr, value, ": " + rangeErrString + " out of range"}
- }
- if err != nil {
- return Time{}, &ParseError{alayout, avalue, stdstr, value, ""}
- }
- }
- if pmSet && hour < 12 {
- hour += 12
- } else if amSet && hour == 12 {
- hour = 0
- }
- if z != nil {
- return Date(year, Month(month), day, hour, min, sec, nsec, z), nil
- }
- if zoneOffset != -1 {
- t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
- t.sec -= int64(zoneOffset)
-
-
- name, offset, _, _, _ := local.lookup(t.sec + internalToUnix)
- if offset == zoneOffset && (zoneName == "" || name == zoneName) {
- t.loc = local
- return t, nil
- }
-
- t.loc = FixedZone(zoneName, zoneOffset)
- return t, nil
- }
- if zoneName != "" {
- t := Date(year, Month(month), day, hour, min, sec, nsec, UTC)
-
-
- offset, _, ok := local.lookupName(zoneName, t.sec+internalToUnix)
- if ok {
- t.sec -= int64(offset)
- t.loc = local
- return t, nil
- }
-
- if len(zoneName) > 3 && zoneName[:3] == "GMT" {
- offset, _ = atoi(zoneName[3:])
- offset *= 3600
- }
- t.loc = FixedZone(zoneName, offset)
- return t, nil
- }
-
- return Date(year, Month(month), day, hour, min, sec, nsec, defaultLocation), nil
- }
- func parseTimeZone(value string) (length int, ok bool) {
- if len(value) < 3 {
- return 0, false
- }
-
- if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
- return 4, true
- }
-
- if value[:3] == "GMT" {
- length = parseGMT(value)
- return length, true
- }
-
- var nUpper int
- for nUpper = 0; nUpper < 6; nUpper++ {
- if nUpper >= len(value) {
- break
- }
- if c := value[nUpper]; c < 'A' || 'Z' < c {
- break
- }
- }
- switch nUpper {
- case 0, 1, 2, 6:
- return 0, false
- case 5:
- if value[4] == 'T' {
- return 5, true
- }
- case 4:
- if value[3] == 'T' {
- return 4, true
- }
- case 3:
- return 3, true
- }
- return 0, false
- }
- func parseGMT(value string) int {
- value = value[3:]
- if len(value) == 0 {
- return 3
- }
- sign := value[0]
- if sign != '-' && sign != '+' {
- return 3
- }
- x, rem, err := leadingInt(value[1:])
- if err != nil {
- return 3
- }
- if sign == '-' {
- x = -x
- }
- if x == 0 || x < -14 || 12 < x {
- return 3
- }
- return 3 + len(value) - len(rem)
- }
- func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
- if value[0] != '.' {
- err = errBad
- return
- }
- if ns, err = atoi(value[1:nbytes]); err != nil {
- return
- }
- if ns < 0 || 1e9 <= ns {
- rangeErrString = "fractional second"
- return
- }
-
-
-
- scaleDigits := 10 - nbytes
- for i := 0; i < scaleDigits; i++ {
- ns *= 10
- }
- return
- }
- var errLeadingInt = errors.New("time: bad [0-9]*")
- func leadingInt(s string) (x int64, rem string, err error) {
- i := 0
- for ; i < len(s); i++ {
- c := s[i]
- if c < '0' || c > '9' {
- break
- }
- if x >= (1<<63-10)/10 {
-
- return 0, "", errLeadingInt
- }
- x = x*10 + int64(c) - '0'
- }
- return x, s[i:], nil
- }
- var unitMap = map[string]float64{
- "ns": float64(Nanosecond),
- "us": float64(Microsecond),
- "µs": float64(Microsecond),
- "μs": float64(Microsecond),
- "ms": float64(Millisecond),
- "s": float64(Second),
- "m": float64(Minute),
- "h": float64(Hour),
- }
- func ParseDuration(s string) (Duration, error) {
-
- orig := s
- f := float64(0)
- neg := false
-
- if s != "" {
- c := s[0]
- if c == '-' || c == '+' {
- neg = c == '-'
- s = s[1:]
- }
- }
-
- if s == "0" {
- return 0, nil
- }
- if s == "" {
- return 0, errors.New("time: invalid duration " + orig)
- }
- for s != "" {
- g := float64(0)
- var x int64
- var err error
-
- if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
- return 0, errors.New("time: invalid duration " + orig)
- }
-
- pl := len(s)
- x, s, err = leadingInt(s)
- if err != nil {
- return 0, errors.New("time: invalid duration " + orig)
- }
- g = float64(x)
- pre := pl != len(s)
-
- post := false
- if s != "" && s[0] == '.' {
- s = s[1:]
- pl := len(s)
- x, s, err = leadingInt(s)
- if err != nil {
- return 0, errors.New("time: invalid duration " + orig)
- }
- scale := 1.0
- for n := pl - len(s); n > 0; n-- {
- scale *= 10
- }
- g += float64(x) / scale
- post = pl != len(s)
- }
- if !pre && !post {
-
- return 0, errors.New("time: invalid duration " + orig)
- }
-
- i := 0
- for ; i < len(s); i++ {
- c := s[i]
- if c == '.' || ('0' <= c && c <= '9') {
- break
- }
- }
- if i == 0 {
- return 0, errors.New("time: missing unit in duration " + orig)
- }
- u := s[:i]
- s = s[i:]
- unit, ok := unitMap[u]
- if !ok {
- return 0, errors.New("time: unknown unit " + u + " in duration " + orig)
- }
- f += g * unit
- }
- if neg {
- f = -f
- }
- if f < float64(-1<<63) || f > float64(1<<63-1) {
- return 0, errors.New("time: overflow parsing duration")
- }
- return Duration(f), nil
- }
|