// parseTime iterates through all known date formats on a normalized time
// string, using Golang's standard lib to do the heavy lifting.
//
// TODO This is a brute-force, "dumb" method of determining the time format and
// should be improved.
963088
func parseTime(t string) (time.Time, error) {
	for _, tf := range timeFormats {
		time, err := time.Parse(tf, t)
		if err == nil {
			log.Debug("timeparse: found format", tf)
			return time, nil
		}
	}
	return time.Time{}, ErrInvalidTimeFormat
}
82831
func ParseDatetime(str string) (Time, error) {
	return ParseTime(str, mysql.TypeDatetime, DefaultFsp)
}
850472
func ParseTime(s string) (t time.Time, err error) {
	formats := []string{rssDate, rssDateV1, rssDateV2, rssDateV3, rssDateV4, time.RFC822, time.RFC822Z}
	for _, format := range formats {
		t, err = time.Parse(format, s)
		if err == nil {
			return
		}
	}
	return
}
1207055
func (pt *ParseTime) US(value string) (time.Time, error) {
	t, _, err := parseUS(value, pt.location)
	return t, err
}
1111785
func Parse(value string) (time.Time, error) {
	for _, ds := range allDateStrings {
		if ds.Match(value) {
			return ds.Parse(value)
		}
	}
	return time.Time{}, &UnknownDateFormatError{value}
}
722606
func parseLyticsTime(ts string) (time.Time, error) {
	var err error

	i, err := strconv.ParseInt(ts, 10, 64)
	if err != nil {
		return time.Now(), err
	}

	tm := time.Unix((i / 1000), 0)

	return tm, err
}
1352022
func ParseTimeFromNum(num int64, tp byte, fsp int) (Time, error) {
	fsp, err := checkFsp(fsp)
	if err != nil {
		return Time{Time: ZeroTime, Type: tp}, errors.Trace(err)
	}

	t, err := parseDateTimeFromNum(num)
	if err != nil {
		return Time{Time: ZeroTime, Type: tp}, errors.Trace(err)
	}

	t.Type = tp
	t.Fsp = fsp
	if err := t.check(); err != nil {
		return Time{Time: ZeroTime, Type: tp}, errors.Trace(err)
	}
	return t, nil
}
886558
func parseDate(date string) (time.Time, error) {
	d, err := time.Parse("1/2/2006", date)
	if err != nil {
		return time.Time{}, err
	}

	return d, nil
}
1187829
func parseTimeOffset(buff []byte, cursor *int, l int) (*time.Location, error) {

	if buff[*cursor] == 'Z' {
		*cursor++
		return time.UTC, nil
	}

	return parseNumericalTimeOffset(buff, cursor, l)
}
410404
func ParseTime(rfc3339Time string) int {
	t, _ := time.Parse(
		time.RFC3339,
		rfc3339Time)

	return TimeToEpoch(t)
}
363670
func (pt *ParseTime) ISO8601(value string) (time.Time, error) {
	t, _, err := parseISO8601(value, pt.location)
	return t, err
}
1162640
func ParseTime(format string, t string) (d time.Time, err error) {
	return time.Parse(format, strings.ToUpper(t))
}
1239780
func (b *builtinDateLiteralSig) evalTime(row chunk.Row) (types.Time, bool, error) {
	mode := b.ctx.GetSessionVars().SQLMode
	if mode.HasNoZeroDateMode() && b.literal.IsZero() {
		return b.literal, true, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(b.literal.String())
	}
	if mode.HasNoZeroInDateMode() && (b.literal.InvalidZero() && !b.literal.IsZero()) {
		return b.literal, true, types.ErrIncorrectDatetimeValue.GenWithStackByArgs(b.literal.String())
	}
	return b.literal, false, nil
}
1068693
func ParseFromTime(t time.Time, nlTime string) []time.Time {
	r := strings.NewReplacer(
		".", "",
		",", "",
		"(", "",
		")", "",
		"'", "",
	)
	nlTime = r.Replace(nlTime)
	nlTime = strings.ToLower(nlTime)
	r = strings.NewReplacer(
		"at ", "",
		"time", "",
		"oclock", "",
		"am", "AM",
		"pm", "PM",
		" am", "AM",
		" pm", "PM",

		// 1st, 2nd, 3rd, 4th, 5th, etc.
		"1st", "1",
		"2nd", "2",
		"3rd", "3",
		"th", "",
		"21st", "21",
		"22nd", "22",
		"23rd", "23",
		"31st", "31",
	)
	nlTime = r.Replace(nlTime)
	nlTime = strings.Title(nlTime)
	if nlTime == "Now" {
		return []time.Time{time.Now()}
	}
	st := strings.Fields(nlTime)
	transform := struct {
		Transform  int
		Type       timeTransform
		Multiplier int
	}{
		Multiplier: 1,
	}
	stFull := ""
	var closeTime bool
	var idxRel int
	var loc *time.Location
	for i := range st {
		// Normalize days
		switch st[i] {
		case "Monday":
			st[i] = "Mon"
			transform.Type = transformDay
		case "Tuesday", "Tues":
			st[i] = "Tue"
			transform.Type = transformDay
		case "Wednesday":
			st[i] = "Wed"
			transform.Type = transformDay
		case "Thursday", "Thur", "Thurs":
			st[i] = "Thu"
			transform.Type = transformDay
		case "Friday":
			st[i] = "Fri"
			transform.Type = transformDay
		case "Saturday":
			st[i] = "Sat"
			transform.Type = transformDay
		case "Sunday":
			st[i] = "Sun"
			transform.Type = transformDay

		// Normalize months
		case "January":
			st[i] = "Jan"
			transform.Type = transformMonth
		case "February":
			st[i] = "Feb"
			transform.Type = transformMonth
		case "March":
			st[i] = "Mar"
			transform.Type = transformMonth
		case "April":
			st[i] = "Apr"
			transform.Type = transformMonth
		case "May":
			// No translation needed for May
			transform.Type = transformMonth
		case "June":
			st[i] = "Jun"
			transform.Type = transformMonth
		case "July":
			st[i] = "Jul"
			transform.Type = transformMonth
		case "August":
			st[i] = "Aug"
			transform.Type = transformMonth
		case "September", "Sept":
			st[i] = "Sep"
			transform.Type = transformMonth
		case "October":
			st[i] = "Oct"
			transform.Type = transformMonth
		case "November":
			st[i] = "Nov"
			transform.Type = transformMonth
		case "December":
			st[i] = "Dec"
			transform.Type = transformMonth

		// If non-deterministic timezone information is provided,
		// e.g. ET or Eastern rather than EST, then load the location.
		// Daylight Savings will be determined on parsing
		case "Pacific", "PT":
			st[i] = ""
			loc = loadLocation("America/Los_Angeles")
		case "Mountain", "MT":
			st[i] = ""
			loc = loadLocation("America/Denver")
		case "Central", "CT":
			st[i] = ""
			loc = loadLocation("America/Chicago")
		case "Eastern", "ET":
			st[i] = ""
			loc = loadLocation("America/New_York")
		// TODO Add the remaining timezones

		// Handle relative times. This currently does not handle
		// complex cases like "in 3 months and 2 days"
		case "Yesterday":
			st[i] = ""
			transform.Type = transformDay
			transform.Transform = 1
			transform.Multiplier = -1
		case "Tomorrow":
			st[i] = ""
			transform.Transform = 1
			transform.Type = transformDay
		case "Today":
			st[i] = ""
			closeTime = true
			transform.Type = transformHour
		case "Ago", "Last":
			st[i] = ""
			transform.Transform = 1
			transform.Multiplier *= -1
		// e.g. "In an hour"
		case "Next", "From", "Now", "In":
			st[i] = ""
			transform.Transform = 1
		case "Later":
			st[i] = ""
			transform.Transform = 6
		case "Hour", "Hours":
			st[i] = ""
			idxRel = i
			closeTime = true
			transform.Type = transformHour
		case "Few", "Couple":
			st[i] = ""
			transform.Transform = 2
		case "Min", "Mins", "Minute", "Minutes":
			st[i] = ""
			idxRel = i
			closeTime = true
			transform.Type = transformMinute
		case "Day", "Days":
			st[i] = ""
			idxRel = i
			transform.Type = transformDay
		case "Week", "Weeks":
			st[i] = ""
			idxRel = i
			transform.Type = transformDay
			transform.Multiplier = 7
		case "Month", "Months":
			st[i] = ""
			idxRel = i
			transform.Type = transformMonth
		case "Year", "Years":
			st[i] = ""
			idxRel = i
			transform.Type = transformYear

		// Remove unnecessary but common expressions like "at", "time",
		// "oclock".
		case "At", "Time", "Oclock", "This", "The":
			st[i] = ""
		case "Noon":
			st[i] = "12PM"
		case "Supper", "Dinner":
			st[i] = "6PM"
		}

		if len(st[i]) > 0 {
			stFull += st[i] + " "
		}
	}
	normalized := strings.TrimRight(stFull, " ")

	var timeEmpty bool
	ts := []time.Time{}
	tme, err := parseTime(normalized)
	if err != nil {
		// Set the hour to 9am
		timeEmpty = true
		tme = time.Now().Round(time.Hour)
		val := 9 - tme.Hour()
		tme = tme.Add(time.Duration(val) * time.Hour)
	}
	if closeTime {
		tme = time.Now().Round(time.Minute)
	}
	ts = append(ts, tme)

	// TODO make more efficient. Handle in switch?
	tloc := timeLocation{loc: loc}
	ctx := &TimeContext{ampm: ampmNoTime, tz: tloc}
	if strings.Contains(normalized, "AM") {
		ctx.ampm = amTime
	}
	if strings.Contains(normalized, "UTC") {
		ctx.tz.utc = true
	}
	for _, ti := range ts {
		ctx = updateContext(ctx, ti, false)
	}

	// Ensure dates are reasonable even in the absence of information.
	// e.g. 2AM should parse to the current year, not 0000
	ctx = completeContext(ctx, t)

	// Loop through a second time to apply the discovered context to each
	// time. Note that this doesn't support context switching,
	// e.g. "5PM CST or PST" or "5PM EST or 6PM PST", which is rare in
	// practice. Future versions may be adapted to support it.
	if ctx.ampm == ampmNoTime {
		halfLen := len(ts)
		// Double size of times for AM/PM
		ts = append(ts, ts...)
		for i := range ts {
			var hour int
			t := ts[i]
			if i < halfLen {
				hour = t.Hour()
			} else {
				hour = t.Hour() + 12
			}
			ts[i] = time.Date(ctx.year,
				ctx.month,
				ctx.day,
				hour,
				t.Minute(),
				t.Second(),
				t.Nanosecond(),
				ctx.tz.loc)
		}
	} else {
		for i := range ts {
			t := ts[i]
			ts[i] = time.Date(ctx.year,
				ctx.month,
				ctx.day,
				t.Hour(),
				t.Minute(),
				t.Second(),
				t.Nanosecond(),
				ctx.tz.loc)
		}
	}

	// If there's no relative transform, we're done.
	if transform.Type == transformInvalid {
		if timeEmpty {
			return []time.Time{}
		}
		if idxRel == 0 {
			return ts
		}
	}

	// Check our idxRel term for the word that preceeds it. If that's a
	// number, e.g. 2 days, then that number is our Transform. Note that
	// this doesn't handle fractional modifiers, like 2.5 days.
	if idxRel > 0 {
		val, err := strconv.Atoi(st[idxRel-1])
		if err == nil {
			transform.Transform = val
		}
	}

	// Apply the transform
	log.Debugf("timeparse: normalized %q. %+v\n", normalized, transform)
	for i := range ts {
		switch transform.Type {
		case transformYear:
			ts[i] = ts[i].AddDate(transform.Transform*transform.Multiplier, 0, 0)
		case transformMonth:
			ts[i] = ts[i].AddDate(0, transform.Multiplier*transform.Transform, 0)
		case transformDay:
			ts[i] = ts[i].AddDate(0, 0, transform.Multiplier*transform.Transform)
		case transformHour:
			ts[i] = ts[i].Add(time.Duration(transform.Transform*transform.Multiplier) * time.Hour)
		case transformMinute:
			ts[i] = ts[i].Add(time.Duration(transform.Transform*transform.Multiplier) * time.Minute)
		}
	}
	log.Debug("timeparse: parsed times", ts)
	return ts
}
853356
func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) {
	vals := make([]time.Time, 0, len(strs))
	for _, str := range strs {
		val, err := time.Parse(format, str)
		if err != nil && returnOnInvalid {
			return nil, err
		}
		if err == nil || addInvalid {
			vals = append(vals, val)
		}
	}
	return vals, nil
}
695632
func parseTime(c *Cell) (string, error) {
	f, err := strconv.ParseFloat(c.Value, 64)
	if err != nil {
		return c.Value, err
	}
	val := TimeFromExcelTime(f, c.date1904)
	format := c.GetNumberFormat()
	// Replace Excel placeholders with Go time placeholders.
	// For example, replace yyyy with 2006. These are in a specific order,
	// due to the fact that m is used in month, minute, and am/pm. It would
	// be easier to fix that with regular expressions, but if it's possible
	// to keep this simple it would be easier to maintain.
	replacements := []struct{ xltime, gotime string }{
		{"yyyy", "2006"},
		{"yy", "06"},
		{"dd", "02"},
		{"d", "2"},
		{"mmm", "Jan"},
		{"mmss", "0405"},
		{"ss", "05"},
		{"hh", "15"},
		{"h", "3"},
		{"mm:", "04:"},
		{":mm", ":04"},
		{"mm", "01"},
		{"am/pm", "pm"},
		{"m/", "1/"},
		{".0", ".9999"},
	}
	for _, repl := range replacements {
		format = strings.Replace(format, repl.xltime, repl.gotime, 1)
	}
	// If the hour is optional, strip it out, along with the
	// possible dangling colon that would remain.
	if val.Hour() < 1 {
		format = strings.Replace(format, "]:", "]", 1)
		format = strings.Replace(format, "[3]", "", 1)
		format = strings.Replace(format, "[15]", "", 1)
	} else {
		format = strings.Replace(format, "[3]", "3", 1)
		format = strings.Replace(format, "[15]", "15", 1)
	}
	return val.Format(format), nil
}
834944
func parsePAXTime(s string) (time.Time, error) {
	const maxNanoSecondDigits = 9

	// Split string into seconds and sub-seconds parts.
	ss, sn := s, ""
	if pos := strings.IndexByte(s, '.'); pos >= 0 {
		ss, sn = s[:pos], s[pos+1:]
	}

	// Parse the seconds.
	secs, err := strconv.ParseInt(ss, 10, 64)
	if err != nil {
		return time.Time{}, ErrHeader
	}
	if len(sn) == 0 {
		return time.Unix(secs, 0), nil // No sub-second values
	}

	// Parse the nanoseconds.
	if strings.Trim(sn, "0123456789") != "" {
		return time.Time{}, ErrHeader
	}
	if len(sn) < maxNanoSecondDigits {
		sn += strings.Repeat("0", maxNanoSecondDigits-len(sn)) // Right pad
	} else {
		sn = sn[:maxNanoSecondDigits] // Right truncate
	}
	nsecs, _ := strconv.ParseInt(sn, 10, 64) // Must succeed
	if len(ss) > 0 && ss[0] == '-' {
		return time.Unix(secs, -1*int64(nsecs)), nil // Negative correction
	}
	return time.Unix(secs, int64(nsecs)), nil
}