func monthName(name string) (month time.Month, charCount int, ok bool) {
	for i := 1; i < 13; i++ {
		m := time.Month(i)
		if strings.HasPrefix(name, strings.ToLower(m.String())) {
			return m, len(m.String()), true
		}
	}
	return 0, 0, false
}
TODO: allow this to match partial months
janu should match janurary
package dateparse
import (
	"fmt"
	"strings"
	"time"
)
func ParseDateWithFormat(date, format string) (time.Time, error) {
	parsers, err := parsersFromFormatString(format)
	if err != nil {
		return time.Time{}, err
	}
	date = strings.TrimSpace(date)
	date = strings.ToLower(date)
	var result datetime
	target := date
	for _, parser := range parsers {
		target = takeAllSpaces(target)
		rest, err := parser(&result, target)
		if err != nil {
			return time.Time{}, err
		}
		target = rest
	}
	return evaluate(result)
}
func parsersFromFormatString(format string) ([]parser, error) {
	parsers := make([]parser, 0, len(format))
	for i := 0; i < len(format); i++ {
		char := format[i]
		if char == '%' {
			if len(format) <= i+1 {
				return nil, fmt.Errorf("\"%%\" found at end of format string")
			}
			specifier := format[i+1]
			parser, ok := formatSpecifiers[specifier]
			if !ok {
				return nil, fmt.Errorf("unknown format specifier \"%c\"", specifier)
			}
			if parser == nil {
				return nil, fmt.Errorf("format specifier \"%c\" not yet supported", specifier)
			}
			parsers = append(parsers, wrapSpecifierParser(parser, specifier))
			i++
		} else {
			parsers = append(parsers, wrapLiteralParser(char))
		}
	}
	return parsers, nil
}
func wrapLiteralParser(literal byte) parser {
	return func(result *datetime, chars string) (rest string, err error) {
		rest, err = literalParser(literal)(result, chars)
		if err != nil {
			return "", ParseLiteralErr{
				Literal: literal,
				Tokens:  chars,
				err:     err,
			}
		}
		return rest, nil
	}
}
func wrapSpecifierParser(p parser, specifier byte) parser {
	return func(result *datetime, chars string) (rest string, err error) {
		rest, err = p(result, chars)
		if err != nil {
			return "", ParseSpecifierErr{
				Specifier: specifier,
				Tokens:    chars,
				err:       err,
			}
		}
		return rest, nil
	}
}
type datetime struct {
	day   *uint
	month *time.Month
	year  *uint
	dayOfYear  *uint
	weekOfYear *uint
	weekday *time.Weekday
	am *bool
	hours        *uint
	minutes      *uint
	seconds      *uint
	miliseconds  *uint
	microseconds *uint
	nanoseconds  *uint
}
type ParseSpecifierErr struct {
	Specifier byte
	Tokens    string
	err       error
}
func (p ParseSpecifierErr) Unwrap() error { return p.err }
func (p ParseSpecifierErr) Error() string {
	return fmt.Sprintf("specifier %%%c failed to parse \"%s\": %s", p.Specifier, p.Tokens, p.err.Error())
}
type ParseLiteralErr struct {
	Literal byte
	Tokens  string
	err     error
}
func (p ParseLiteralErr) Unwrap() error { return p.err }
func (p ParseLiteralErr) Error() string {
	return fmt.Sprintf("literal %c not matched in \"%s\": %s", p.Literal, p.Tokens, p.err.Error())
}
var formatSpecifiers = map[byte]parser{
	'a': parseWeedayAbbreviation,
	'b': parseMonthAbbreviation,
	'c': parseMonthNumeric,
	'D': parseDayNumericWithEnglishSuffix,
	'd': parseDayOfMonthNumeric,
	'e': parseDayOfMonthNumeric,
	'f': parseMicrosecondsNumeric,
	'H': parse24HourNumeric,
	'h': parse12HourNumeric,
	'I': parse12HourNumeric,
	'i': parseMinuteNumeric,
	'j': parseDayOfYearNumeric,
	'k': parse24HourNumeric,
	'l': parse12HourNumeric,
	'M': parseMonthName,
	'm': parseMonthNumeric,
	'p': parseAmPm,
	'r': parse12HourTimestamp,
	'S': parseSecondsNumeric,
	's': parseSecondsNumeric,
	'T': parse24HourTimestamp,
	'U': nil,
	'u': nil,
	'V': nil,
	'v': nil,
	'W': nil,
	'w': nil,
	'X': nil,
	'x': nil,
	'Y': parseYear4DigitNumeric,
	'y': parseYear2DigitNumeric,
	'%': literalParser('%'),
}
func boolPtr(a bool) *bool { return &a }
func weekdayAbbrev(abbrev string) (time.Weekday, bool) {
	switch abbrev {
	case "sun":
		return time.Sunday, true
	case "mon":
		return time.Monday, true
	case "tue":
		return time.Tuesday, true
	case "wed":
		return time.Wednesday, true
	case "thu":
		return time.Thursday, true
	case "fri":
		return time.Friday, true
	case "sat":
		return time.Saturday, true
	}
	return 0, false
}
func monthAbbrev(abbrev string) (time.Month, bool) {
	switch abbrev {
	case "jan":
		return time.January, true
	case "feb":
		return time.February, true
	case "mar":
		return time.March, true
	case "apr":
		return time.April, true
	case "may":
		return time.May, true
	case "jun":
		return time.June, true
	case "jul":
		return time.July, true
	case "aug":
		return time.August, true
	case "sep":
		return time.September, true
	case "oct":
		return time.October, true
	case "nov":
		return time.November, true
	case "dec":
		return time.December, true
	}
	return 0, false
}