func lexTimestamp(x *Lexer) stateFn {
	// Set defaults for all our our values so that we can safely check them all
	// later without worrying about which ones were set.
	year := [4]byte{x.input[x.pos-5], x.input[x.pos-4], x.input[x.pos-3], x.input[x.pos-2]}
	month := [2]byte{'0', '1'}
	day, hour, hourOffset := month, month, month

	// Overall form can be some subset of yyyy-mm-ddThh:mm:ss.sssTZD.  The "yyyy-"
	// has already been lexed.  Comments will show the progression in parsing.
	// yyyy-mm
	if !isMonthStart(x.next()) || !isNumber(x.next()) {
		x.backup()
		return x.errorf("invalid character as month part of timestamp: %#U", x.next())
	}
	month[0], month[1] = x.input[x.pos-2], x.input[x.pos-1]

	// yyyy-mmT or yyyy-mm-
	switch ch := x.next(); {
	case ch == 'T':
		if pk := x.peek(); !isNumericStop(pk) && pk != eof {
			return x.errorf("invalid timestamp stop character: %#U", pk)
		}
		return validateDateAndEmit(x, year, month, day, hour, hourOffset)
	case ch == '-':
	// Do nothing, a dash means we're going into days.
	default:
		return x.errorf("invalid character after month part of timestamp: %#U", ch)
	}

	// yyyy-mm-dd
	if !isDayStart(x.next()) || !isNumber(x.next()) {
		x.backup()
		return x.errorf("invalid character as day part of timestamp: %#U", x.next())
	}
	day[0], day[1] = x.input[x.pos-2], x.input[x.pos-1]

	// The day portion does not need to be terminated by a 'T' to be a valid timestamp.
	// yyyy-mm-dd or yyyy-mm-ddT
	switch ch := x.next(); {
	case ch == 'T':
		if pk := x.peek(); isNumericStop(pk) || pk == eof {
			return validateDateAndEmit(x, year, month, day, hour, hourOffset)
		}
	case isNumericStop(ch):
		x.backup()
		return validateDateAndEmit(x, year, month, day, hour, hourOffset)
	default:
		return x.errorf("invalid character after day part of timestamp: %#U", ch)
	}

	// yyyy-mm-ddThh:mm
	if !isHourStart(x.next()) || !isNumber(x.next()) || x.next() != ':' || !isMinuteStart(x.next()) || !isNumber(x.next()) {
		x.backup()
		return x.errorf("invalid character as hour/minute part of timestamp: %#U", x.next())
	}
	hour[0], hour[1] = x.input[x.pos-5], x.input[x.pos-4]

	// yyyy-mm-ddThh:mm:ss(.sss)?
	if x.peek() == ':' {
		x.next()
		// yyyy-mm-ddThh:mm:ss
		if !isMinuteStart(x.next()) || !isNumber(x.next()) {
			x.backup()
			return x.errorf("invalid character as seconds part of timestamp: %#U", x.next())
		}
		// yyyy-mm-ddThh:mm:ss.sss (can be any number of digits)
		if x.peek() == '.' {
			x.next()
			// There must be at least one number after the period.
			if !isNumber(x.peek()) {
				return x.error("missing fractional seconds value")
			}
			for isNumber(x.peek()) {
				x.next()
			}
		}
	}

	// If the time is included, then there must be a timezone component.
	// https://www.w3.org/TR/NOTE-datetime
	// yyyy-mm-ddThh:mm:ss(.sss)?TZD
	switch ch := x.next(); {
	case ch == '+' || ch == '-':
		// TZD == +hh:mm or -hh:mm
		if !isHourStart(x.next()) || !isNumber(x.next()) || x.next() != ':' || !isMinuteStart(x.next()) || !isNumber(x.next()) {
			x.backup()
			return x.errorf("invalid character as hour/minute part of timezone: %#U", x.next())
		}
		hourOffset[0], hourOffset[1] = x.input[x.pos-5], x.input[x.pos-4]
	case ch == 'Z':
		// Do nothing. 'Z' is a great way to end a timestamp.
	default:
		return x.errorf("invalid character as timezone part of timestamp: %#U", ch)
	}

	if ch := x.peek(); !isNumericStop(ch) && ch != eof {
		return x.errorf("invalid timestamp stop character: %#U", ch)
	}

	return validateDateAndEmit(x, year, month, day, hour, hourOffset)
}
// lexTimestamp lexes everything past the first "-" in a timestamp.  It is assumed that
// the year and dash have been consumed.
lexTimestamp lexes everything past the first "-" in a timestamp.  It is assumed that
the year and dash have been consumed.
// lexTimestamp lexes everything past the first " - " in a timestamp . It is assumed that // the year and dash have been consumed .
func lexTimestamp(x *Lexer) stateFn {
	year := [4]byte{x.input[x.pos-5], x.input[x.pos-4], x.input[x.pos-3], x.input[x.pos-2]}
	month := [2]byte{'0', '1'}
	day, hour, hourOffset := month, month, month
	if !isMonthStart(x.next()) || !isNumber(x.next()) {
		x.backup()
		return x.errorf("invalid character as month part of timestamp: %#U", x.next())
	}
	month[0], month[1] = x.input[x.pos-2], x.input[x.pos-1]
	T or yyyy-mm-
	switch ch := x.next(); {
	case ch == 'T':
		if pk := x.peek(); !isNumericStop(pk) && pk != eof {
			return x.errorf("invalid timestamp stop character: %#U", pk)
		}
		return validateDateAndEmit(x, year, month, day, hour, hourOffset)
	case ch == '-':
	default:
		return x.errorf("invalid character after month part of timestamp: %#U", ch)
	}
	-dd
	if !isDayStart(x.next()) || !isNumber(x.next()) {
		x.backup()
		return x.errorf("invalid character as day part of timestamp: %#U", x.next())
	}
	day[0], day[1] = x.input[x.pos-2], x.input[x.pos-1]
	-dd or yyyy-mm-ddT
	switch ch := x.next(); {
	case ch == 'T':
		if pk := x.peek(); isNumericStop(pk) || pk == eof {
			return validateDateAndEmit(x, year, month, day, hour, hourOffset)
		}
	case isNumericStop(ch):
		x.backup()
		return validateDateAndEmit(x, year, month, day, hour, hourOffset)
	default:
		return x.errorf("invalid character after day part of timestamp: %#U", ch)
	}
	-ddThh:mm
	if !isHourStart(x.next()) || !isNumber(x.next()) || x.next() != ':' || !isMinuteStart(x.next()) || !isNumber(x.next()) {
		x.backup()
		return x.errorf("invalid character as hour/minute part of timestamp: %#U", x.next())
	}
	hour[0], hour[1] = x.input[x.pos-5], x.input[x.pos-4]
	-ddThh:mm:ss(.sss)?
	if x.peek() == ':' {
		x.next()
		-ddThh:mm:ss
		if !isMinuteStart(x.next()) || !isNumber(x.next()) {
			x.backup()
			return x.errorf("invalid character as seconds part of timestamp: %#U", x.next())
		}
		-ddThh:mm:ss.sss (can be any number of digits)
		if x.peek() == '.' {
			x.next()
			if !isNumber(x.peek()) {
				return x.error("missing fractional seconds value")
			}
			for isNumber(x.peek()) {
				x.next()
			}
		}
	}
	-ddThh:mm:ss(.sss)?TZD
	switch ch := x.next(); {
	case ch == '+' || ch == '-':
		if !isHourStart(x.next()) || !isNumber(x.next()) || x.next() != ':' || !isMinuteStart(x.next()) || !isNumber(x.next()) {
			x.backup()
			return x.errorf("invalid character as hour/minute part of timezone: %#U", x.next())
		}
		hourOffset[0], hourOffset[1] = x.input[x.pos-5], x.input[x.pos-4]
	case ch == 'Z':
	default:
		return x.errorf("invalid character as timezone part of timestamp: %#U", ch)
	}
	if ch := x.peek(); !isNumericStop(ch) && ch != eof {
		return x.errorf("invalid timestamp stop character: %#U", ch)
	}
	return validateDateAndEmit(x, year, month, day, hour, hourOffset)
}
func lexTimestamp ( x * Lexer ) stateFn { year := [ 4 ] byte { x . input [ x . pos - 5 ] , x . input [ x . pos - 4 ] , x . input [ x . pos - 3 ] , x . input [ x . pos - 2 ] } month := [ 2 ] byte { '0' , '1' } day , hour , hourOffset := month , month , month if ! isMonthStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) { x . backup ( ) return x . errorf ( " " , x . next ( ) ) } month [ 0 ] , month [ 1 ] = x . input [ x . pos - 2 ] , x . input [ x . pos - 1 ] switch ch := x . next ( ) ; { case ch == 'T' : if pk := x . peek ( ) ; ! isNumericStop ( pk ) && pk != eof { return x . errorf ( " " , pk ) } return validateDateAndEmit ( x , year , month , day , hour , hourOffset ) case ch == '-' : default : return x . errorf ( " " , ch ) } if ! isDayStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) { x . backup ( ) return x . errorf ( " " , x . next ( ) ) } day [ 0 ] , day [ 1 ] = x . input [ x . pos - 2 ] , x . input [ x . pos - 1 ] switch ch := x . next ( ) ; { case ch == 'T' : if pk := x . peek ( ) ; isNumericStop ( pk ) || pk == eof { return validateDateAndEmit ( x , year , month , day , hour , hourOffset ) } case isNumericStop ( ch ) : x . backup ( ) return validateDateAndEmit ( x , year , month , day , hour , hourOffset ) default : return x . errorf ( " " , ch ) } if ! isHourStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) || x . next ( ) != ':' || ! isMinuteStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) { x . backup ( ) return x . errorf ( " " , x . next ( ) ) } hour [ 0 ] , hour [ 1 ] = x . input [ x . pos - 5 ] , x . input [ x . pos - 4 ] if x . peek ( ) == ':' { x . next ( ) if ! isMinuteStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) { x . backup ( ) return x . errorf ( " " , x . next ( ) ) } if x . peek ( ) == '.' { x . next ( ) if ! isNumber ( x . peek ( ) ) { return x . error ( " " ) } for isNumber ( x . peek ( ) ) { x . next ( ) } } } switch ch := x . next ( ) ; { case ch == '+' || ch == '-' : if ! isHourStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) || x . next ( ) != ':' || ! isMinuteStart ( x . next ( ) ) || ! isNumber ( x . next ( ) ) { x . backup ( ) return x . errorf ( " " , x . next ( ) ) } hourOffset [ 0 ] , hourOffset [ 1 ] = x . input [ x . pos - 5 ] , x . input [ x . pos - 4 ] case ch == 'Z' : default : return x . errorf ( " " , ch ) } if ch := x . peek ( ) ; ! isNumericStop ( ch ) && ch != eof { return x . errorf ( " " , ch ) } return validateDateAndEmit ( x , year , month , day , hour , hourOffset ) }
lexTimestamp lexes everything past the first "-" in a timestamp.
lexTimestamp lexes everything past the first " - " in a timestamp .
// Set defaults for all our our values so that we can safely check them all // later without worrying about which ones were set. // Overall form can be some subset of yyyy-mm-ddThh:mm:ss.sssTZD.  The "yyyy-" // has already been lexed.  Comments will show the progression in parsing. // yyyy-mm // yyyy-mmT or yyyy-mm- // Do nothing, a dash means we're going into days. // yyyy-mm-dd // The day portion does not need to be terminated by a 'T' to be a valid timestamp. // yyyy-mm-dd or yyyy-mm-ddT // yyyy-mm-ddThh:mm // yyyy-mm-ddThh:mm:ss(.sss)? // yyyy-mm-ddThh:mm:ss // yyyy-mm-ddThh:mm:ss.sss (can be any number of digits) // There must be at least one number after the period. // If the time is included, then there must be a timezone component. // https://www.w3.org/TR/NOTE-datetime // yyyy-mm-ddThh:mm:ss(.sss)?TZD // TZD == +hh:mm or -hh:mm // Do nothing. 'Z' is a great way to end a timestamp.