carbon icon indicating copy to clipboard operation
carbon copied to clipboard

Parse method is too strict and not general enough, I hope it can be smarter, such as the following parsing method, which is relatively efficient and general

Open canuran opened this issue 3 years ago • 2 comments

下面这种方式可以很好地兼容 分隔符 和 0补位 两种日期格式,而不是有了分隔符还需要0补位 ` var dateFieldLens = [9]int{4, 2, 2, 2, 2, 2, 9, 2, 2}

// ParseGeneralDate 解析任意字段有序的日期 // 顺序必须是:年月日时分秒纳秒,兼容ISO8601UTC时区 // 时间字段可以是任意分隔符或填充位数,示例如下: // 2022年8月21日19点18分38秒123456789纳秒 // 20220821191838.123456789 // 2022-8-21T19:18:38.123456789+8:30 // 2022-8-21 19:18:38Z(可以没有纳秒) // 2022-8-21(可以没有时间,甚至可以没有日期) func ParseGeneralDate(input []rune) time.Time { dateFields := [9]int{1, 1, 1} var fieldNum int var fieldLen int var zoneRune rune var nanoTimes = 1000000000

// 提取日期字段
for _, r := range input {
	if r <= '9' && r >= '0' {
		fieldLen++
		if fieldNum == 6 {
			nanoTimes /= 10 // 纳秒是小数形式
		}
		if fieldLen == 1 { // 覆盖字段
			dateFields[fieldNum] = int(r - '0')
		} else if fieldLen == dateFieldLens[fieldNum] { // 字段已满
			dateFields[fieldNum] = dateFields[fieldNum]*10 + int(r-'0')
			if fieldNum > 7 {
				break
			}
			fieldNum++
			fieldLen = 0
		} else { // 追加字段
			dateFields[fieldNum] = dateFields[fieldNum]*10 + int(r-'0')
		}
	} else {
		// 当前字段长度大于0则进入下一个字段
		if fieldLen > 0 {
			if fieldNum > 7 {
				break
			}
			fieldNum++
			fieldLen = 0
		}

		// 处理时区,遵循ISO8601:UTC时区
		if fieldNum > 5 {
			if r == 'Z' { // 结束遍历
				zoneRune = r
				break
			}
			if r == '+' || r == '-' { // 跳转时区字段
				zoneRune = r
				fieldNum = 7
			}
		}
	}
}

// 计算时区与偏移
timeZone := time.Local
if zoneRune == 'Z' {
	timeZone = time.UTC
} else if zoneRune == '+' {
	timeZone = time.FixedZone("", dateFields[7]*3600+dateFields[8]*60)
} else if zoneRune == '-' {
	timeZone = time.FixedZone("", -dateFields[7]*3600-dateFields[8]*60)
}

return time.Date(dateFields[0], time.Month(dateFields[1]), dateFields[2],
	dateFields[3], dateFields[4], dateFields[5], dateFields[6]*nanoTimes, timeZone)

} `

canuran avatar Sep 09 '22 07:09 canuran

The issue body's language is not English, translate it automatically, please use English next time. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿


` var dateFieldLens = [9]int{4, 2, 2, 2, 2, 2, 9, 2, 2}

// ParseGeneralDate parses any field ordered date // The order must be: year, month, day, hour, minute, second, nanosecond, compatible with ISO8601UTC time zone // The time field can be any delimiter or number of padding digits, examples are as follows: // Aug 21, 2022 19:18:38 123456789 ns // 20220821191838.123456789 // 2022-8-21T19:18:38.123456789+8:30 // 2022-8-21 19:18:38Z (can be without nanoseconds) // 2022-8-21 (can have no time or even no date) func ParseGeneralDate(input []rune) time.Time { dateFields := [9]int{1, 1, 1} var fieldNum int var fieldLen int var zoneRune rune var nanoTimes = 1000000000

// extract the date field for _, r := range input { if r <= '9' && r >= '0' { fieldLen++ if fieldNum == 6 { nanoTimes /= 10 // nanoseconds are in decimal form } if fieldLen == 1 { // override field dateFields[fieldNum] = int(r - '0') } else if fieldLen == dateFieldLens[fieldNum] { // field is full dateFields[fieldNum] = dateFields[fieldNum]*10 + int(r-'0') if fieldNum > 7 { break } fieldNum++ fieldLen = 0 } else { // append field dateFields[fieldNum] = dateFields[fieldNum]*10 + int(r-'0') } } else { // If the current field length is greater than 0, enter the next field if fieldLen > 0 { if fieldNum > 7 { break } fieldNum++ fieldLen = 0 }

// handle time zone, follow ISO8601: UTC time zone if fieldNum > 5 { if r == 'Z' { // end traversal zoneRune = r break } if r == '+' || r == '-' { // jump to the time zone field zoneRune = r fieldNum = 7 } } } }

// Calculate time zone and offset timeZone := time.Local if zoneRune == 'Z' { timeZone = time.UTC } else if zoneRune == '+' { timeZone = time.FixedZone("", dateFields[7]*3600+dateFields[8]*60) } else if zoneRune == '-' { timeZone = time.FixedZone("", -dateFields[7]*3600-dateFields[8]*60) }

return time.Date(dateFields[0], time.Month(dateFields[1]), dateFields[2], dateFields[3], dateFields[4], dateFields[5], dateFields[6]*nanoTimes, timeZone) } `

Issues-translate-bot avatar Sep 09 '22 07:09 Issues-translate-bot

Thanks,you can pull a request

open-git avatar Sep 09 '22 09:09 open-git

It has been fixed in 1.7.0 or 2.2.0

kuafuRace avatar Oct 27 '22 02:10 kuafuRace