func regexpMap(format string) string {
	re := format
	for _, t := range terms {
		re = strings.Replace(re, t.format, t.expr, -1)
	}
	return re
}
regexpMap builds regular expression for a particular date format
the resulting regexp can be used in order to locate the date in a line,
see terms table above
package date
import (
	"fmt"
	"regexp"
	"strings"
	"time"
	"unsafe"
)
type (
	Parser interface {
		Parse(buf []byte) (time.Time, *Format)
	}
	Format struct {
		frmt        string          
		dLayout     string          
		dRegexp     *regexp.Regexp  
		hasLocation bool            
		hasYear     bool            
		noDate      bool            
	}
	parser struct {
		Parser
		formats []*Format
	}
	term struct {
		format string
		layout string
		expr   string
	}
)
const (
	dateGroup = "date"
)
var (
	KnownFormats = []string{
		"MMM D, YYYY h:mm:ss P",
		"DDD MMM _D HH:mm:ss YYYY",
		"DDD MMM _D HH:mm:ss MST YYYY",
		"DDD MMM DD HH:mm:ss ZZZZ YYYY",
		"DDDD, YY-MMM-DD HH:mm:ss ZZZ",
		"DDD, DD MMM YYYY HH:mm:ss ZZZ",
		"DDD, DD MMM YYYY HH:mm:ss ZZZZ",
		"DDD, D MMM YYYY HH:mm:ss ZZZZ",
		"DD MMM YYYY, HH:mm",
		"YYYY-MMM-DD",
		"DD MMMM YYYY",
		"DD/MM/YYYY HH:mm:ss.SSS",
		"DD/MM/YYYY HH:mm:ss",
		"D/MM/YYYY HH:mm:ss",
		"DD/M/YYYY HH:mm:ss",
		"D/M/YYYY HH:mm:ss",
		"D/M/YYYY hh:mm:ss P",
		"DD/MM/YYYY HH:mm",
		"D/M/YYYY HH:mm",
		"D/M/YY HH:mm",
		"D/M/YYYY hh:mm P",
		"D/M/YYYY h:mm P",
		"DD/MMM/YYYY:HH:mm:ss ZZZZ",
		"DD/MM/YYYY",
		"D/MM/YYYY",
		"DD/MM/YY",
		"D/M/YY",
		"YYYY/MM/DD HH:mm:ss.SSS",
		"YYYY/MM/DD HH:mm:ss",
		"YYYY/MM/D HH:mm:ss",
		"YYYY/M/DD HH:mm:ss",
		"YYYY/MM/DD HH:mm",
		"YYYY/M/D HH:mm",
		"YYYY/MM/DD",
		"YYYY/M/DD",
		"YYYY-MM-DDTHH:mm:ss.SSSZZZZ",
		"YYYY-MM-DDTHH:mm:ss.SSSZ",
		"YYYY-MM-DDTHH:mm:ssZZZZZ",
		"YYYY-MM-DDTHH:mm:ssZZZZ",
		"YYYY-MM-DDTHH:mm:ssZ",
		"YYYY-MM-DDTHH:mm:ss",
		"YYYY-MM-DD HH:mm:ss.SSS ZZZZ ZZZ",
		"YYYY-MM-DD HH:mm:ss.SSS",
		"YYYY-MM-DD HH:mm:ss ZZZZZ",
		"YYYY-MM-DD HH:mm:ssZZZZZ",
		"YYYY-MM-DD HH:mm:ss ZZZZ ZZZ",
		"YYYY-MM-DD HH:mm:ss ZZZZ",
		"YYYY-MM-DD HH:mm:ss ZZZ",
		"YYYY-MM-DD hh:mm:ss P",
		"YYYY-MM-DD HH:mm:ss",
		"YYYY-MM-DD  HH:mm:ss",
		"YYYY-MM-DD HH:mm",
		"YYYY-MM-DD",
		"MM.DD.YYYY",
		"MM.DD.YY",
		"DDD MMM _D HH:mm:ss.SSS",
		"DDD MMM DD HH:mm:ss.SSS",
		"MMM DD HH:mm:ss",
		"MMM _D HH:mm:ss",
	}
	terms = []term{
		{"YYYY", "2006", "[1-2]\\d{3}"},
		{"YY", "06", "\\d{2}"},
		{"MMMM", "January", "[A-Z][a-z]{2,8}"},
		{"MMM", "Jan", "[A-Z][a-z]{2}"},
		{"MM", "01", "[0-3]\\d"},
		{"M", "1", "\\d{1,2}"},
		{"DDDD", "Monday", "[A-Z][a-z]{5,7}"},
		{"DDD", "Mon", "[A-Z][a-z]{2}"},
		{"DD", "02", "\\d{2}"},
		{"_D", "_2", "(?: \\d{1}|\\d{2})"},
		{"D", "2", "\\d{1,2}"},
		{"HH", "15", "\\d{2}"},
		{"hh", "03", "\\d{2}"},
		{"h", "3", "\\d{1,2}"},
		{"mm", "04", "\\d{2}"},
		{"m", "4", "\\d{1,2}"},
		{"ss", "05", "\\d{2}"},
		{"s", "5", "\\d{1,2}"},
		{".SSS", ".999999999", ".\\d{3,}"},
		{"P", "PM", "(?:am|AM|pm|PM)"},
		{"ZZZZZ", "-07:00", "[+-][0-9]{2}:[0-9]{2}"},
		{"ZZZZ", "-0700", "[+-][0-9]{4}"},
		{"ZZZ", "MST", "[A-Z]{3}"},
		{"ZZ", "Z07:00", "Z[0-9]{2}:[0-9]{2}"},
	}
	defParser = NewDefaultParser()
)
func Parse(data []byte) (time.Time, error) {
	tm, f := defParser.Parse(data)
	if f == nil {
		return tm, fmt.Errorf("Could not parse data %s, no such default format for it, or it is wrong date/time", data)
	}
	return tm, nil
}
func NewDefaultParser(usrFmts ...string) *parser {
	if len(usrFmts) == 0 {
		return NewParser(KnownFormats...)
	}
	dtFmts := make([]string, 0, len(KnownFormats)+len(usrFmts))
	dtFmts = append(dtFmts, usrFmts...)       
	dtFmts = append(dtFmts, KnownFormats...)  
	return NewParser(dtFmts...)
}
func NewParser(fmts ...string) *parser {
	p := new(parser)
	p.formats = make([]*Format, len(fmts))
	for i, fmtStr := range fmts {
		noDate := !strings.ContainsAny(fmtStr, "YMD")
		hasYear := !noDate && strings.Contains(fmtStr, "Y")
		hasLocation := strings.Contains(fmtStr, "Z")
		dRegexp := regexp.MustCompile(fmt.Sprintf("(?P<%v>%v)", dateGroup, regexpMap(fmtStr)))
		grps := dRegexp.SubexpNames()
		if len(grps) < 2 || grps[1] != dateGroup {  
			panic(fmt.Sprintf("regular expression=%s doesn't have "+
				"required '%s' group", dRegexp, dateGroup))
		}
		p.formats[i] = &Format{
			frmt:        fmtStr,
			dLayout:     dateMap(fmtStr),
			dRegexp:     dRegexp,
			hasLocation: hasLocation,
			hasYear:     hasYear,
			noDate:      noDate,
		}
	}
	return p
}
func (p *parser) Parse(buf []byte) (time.Time, *Format) {
	for _, dFmt := range p.formats {
		tm, err := dFmt.Parse(buf)
		if err == nil {
			return tm, dFmt
		}
	}
	return time.Time{}, nil
}
func dateMap(format string) string {
	layout := format
	for _, t := range terms {
		layout = strings.Replace(layout, t.format, t.layout, -1)
	}
	return layout
}