v8.run/go/exp@v0.0.26-0.20230226010534-afcdbd3f782d/time2/timeparse/8601.go (about) 1 package timeparse 2 3 import ( 4 "strconv" 5 "strings" 6 "time" 7 ) 8 9 func Parse8601(data string) (unix, nano, offset int64) { 10 idx := strings.LastIndexAny(data, "T ") 11 var dt string = data 12 var tt string = "00:00:00.00Z" 13 if idx > 0 { 14 dt = data[:idx] 15 tt = data[idx+1:] 16 } 17 18 var year, month, day string 19 20 // Parse date 21 22 idx = strings.IndexAny(dt, "-/ ") 23 if idx == -1 { 24 // Year only 25 year = dt 26 } else { 27 year = dt[:idx] 28 dt = dt[idx+1:] 29 30 idx = strings.IndexAny(dt, "-/ ") 31 if idx == -1 { 32 // Year and month 33 month = dt 34 } else { 35 month = dt[:idx] 36 day = dt[idx+1:] 37 } 38 } 39 40 // Parse time 41 42 var hour, min, sec string 43 var TZ string = "Z" 44 45 // Split time and timezone 46 idx = strings.LastIndexAny(tt, "Z+-") 47 if idx > 0 { 48 TZ = tt[idx:] 49 tt = tt[:idx] 50 } 51 52 idx = strings.IndexAny(tt, ":") 53 if idx == -1 { 54 if len(tt) <= 2 { 55 // Hour only 56 hour = tt 57 } else { 58 // Maybe HHMMSS 59 hour = tt[:2] 60 tt = tt[2:] 61 if len(tt) >= 2 { 62 min = tt[:2] 63 sec = tt[2:] 64 } 65 } 66 } else { 67 hour = tt[:idx] 68 tt = tt[idx+1:] 69 70 idx = strings.IndexAny(tt, ":") 71 if idx == -1 { 72 // Hour and minute 73 min = tt 74 } else { 75 min = tt[:idx] 76 sec = tt[idx+1:] 77 } 78 } 79 80 // Parse timezone 81 82 if TZ != "Z" { 83 // +HH 84 // +HHMM 85 // +HH:MM 86 // -HH 87 88 var hh, mm string = "00", "00" 89 var sign int64 = 0 90 91 if len(TZ) > 0 { 92 if TZ[0] == '-' { 93 sign = -1 94 } else if TZ[0] == '+' { 95 sign = 1 96 } 97 TZ = TZ[1:] 98 99 if len(TZ) > 2 { 100 hh = TZ[:2] 101 mm = strings.TrimLeft(TZ[2:], ":") 102 } else { 103 hh = TZ 104 } 105 } 106 107 offh, err := strconv.Atoi(hh) 108 if err != nil { 109 offh = 0 110 } 111 offm, err := strconv.Atoi(mm) 112 if err != nil { 113 offm = 0 114 } 115 116 offset = int64(offh*3600+offm*60) * sign 117 } 118 119 // Parse Strings 120 yeari, err := strconv.Atoi(year) 121 if err != nil { 122 yeari = 1970 123 } 124 monthi, err := strconv.Atoi(month) 125 if err != nil || monthi < 1 || monthi > 12 { 126 monthi = 1 127 } 128 dayi, err := strconv.Atoi(day) 129 if err != nil || dayi < 1 || dayi > 31 { 130 dayi = 1 131 } 132 houri, err := strconv.Atoi(hour) 133 if err != nil || houri < 0 || houri > 23 { 134 houri = 0 135 } 136 mini, err := strconv.Atoi(min) 137 if err != nil || mini < 0 || mini > 59 { 138 mini = 0 139 } 140 // Parse seconds 141 secf, err := strconv.ParseFloat(sec, 64) 142 if err != nil || secf < 0 || secf >= 60 { 143 secf = 0 144 } 145 146 // Calculate seci and nano 147 seci := int64(secf) 148 nano = int64((secf - float64(seci)) * 1e9) 149 150 // Calculate unix 151 ttt := time.Date(yeari, time.Month(monthi), dayi, houri, mini, int(seci), int(nano), time.UTC) 152 153 return ttt.Unix() - offset, nano, offset 154 }