// dateOrZero parses datestr with the given format and returns the resulting
// time and error. An empty datestr is not an error and yields a zero time. format
// defaults to time.RFC3339 if empty.
439379
func dateOrZero(datestr, format string) (time.Time, error) {
	if datestr == "" {
		return time.Time{}, nil
	}
	if format == "" {
		format = time.RFC3339
	}
	return time.Parse(format, datestr)
}
560579
func (t Time) InvalidZero() bool {
	return t.Time.Month() == 0 || t.Time.Day() == 0
}
878111
func (f Filter) Date(date string) Filter {
	f.Op = "isDate"
	f.Val = nil
	return f.Opt("date", []string{date})
}
697155
func (a *AttributeDefinition) AllNonZero() []string {
	nzs := make([]string, len(a.NonZeroAttributes))
	i := 0
	for n := range a.NonZeroAttributes {
		nzs[i] = n
		i++
	}
	return nzs
}
242166
func (date Date) MarshalJSON() ([]byte, error) {
	if date.IsZero() {
		return []byte("null"), nil
	}
	return []byte(`"` + date.format() + `"`), nil
}
936698
func ParseStrict(datestr string) (time.Time, error) {
	p, err := parseTime(datestr, nil)
	if err != nil {
		return time.Time{}, err
	}
	if p.ambiguousMD {
		return time.Time{}, ErrAmbiguousMMDD
	}
	return p.parse()
}
334584
func DateParse(dateString, format string) (time.Time, error) {
	return time.ParseInLocation(ConvDateFormat(format), dateString, time.Local)
}
902566
func (r ContinuousRange) IsZero() bool {
	return (r.Min == 0 || math.IsNaN(r.Min)) &&
		(r.Max == 0 || math.IsNaN(r.Max)) &&
		r.Domain == 0
}
952529
func (a *Duration) IsZero() bool {
	for i := range a.Node.Values {
		if a.Node.Values[i].Magnitude != 0 {
			return false
		}
	}
	return true
}
1225929
func (m *Time) MarshalTo(data []byte) (int, error) {
	if m == nil || m.Time.IsZero() {
		return 0, nil
	}
	return m.ProtoTime().MarshalTo(data)
}
1184050
func (c *cState) encodeZero(symbolTT symbolTransform) {
	nbBitsOut := (uint32(c.state) + symbolTT.deltaNbBits) >> 16
	dstState := int32(c.state>>(nbBitsOut&15)) + symbolTT.deltaFindState
	c.bw.addBits16ZeroNC(c.state, uint8(nbBitsOut))
	c.state = c.stateTable[dstState]
}
736408
func isNonZero(v *Version) bool {
	if v.Major() != 0 || v.Minor() != 0 || v.Patch() != 0 || v.Prerelease() != "" {
		return true
	}

	return false
}
671279
func (d DateTime) Date(v reflect.Value) (interface{}, error) {
	return d.date(), nil
}
912104
func DateFor(year int, month time.Month, day int) Date {
	return Date{
		t: time.Date(year, month, day, 0, 0, 0, 0, time.UTC),
	}
}
389871
func LeftPadZero(input string, padLength int) string {
	return fmt.Sprintf(`%0*s`, padLength, input)
}
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
}
1275716
func extractDayMicrosecond(format string) (int64, int64, int64, gotime.Duration, error) {
	fields := strings.Split(format, " ")
	if len(fields) != 2 {
		return 0, 0, 0, 0, errors.Errorf("invalid time format - %s", format)
	}

	days, err := strconv.ParseInt(fields[0], 10, 64)
	if err != nil {
		return 0, 0, 0, 0, errors.Errorf("invalid time format - %s", format)
	}

	_, _, _, value, err := extractHourMicrosecond(fields[1])
	if err != nil {
		return 0, 0, 0, 0, errors.Errorf("invalid time format - %s", format)
	}

	return 0, 0, days, value, nil
}