commit 3711f308e4f654122dab629773f66bc279b97acf Author: Aaron Raddon Date: Sun Apr 20 19:56:17 2014 -0700 initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/parseany.go b/parseany.go new file mode 100644 index 0000000..66bd6f9 --- /dev/null +++ b/parseany.go @@ -0,0 +1,210 @@ +package dateparse + +import ( + "fmt" + u "github.com/araddon/gou" + "time" + "unicode" + //"unicode/utf8" +) + +var _ = u.EMPTY + +const ( + S_START = 0 + S_NUMERIC = 1 + S_COMMA = 2 + S_SEMICOLON = 3 + S_COLON = 4 + S_AMPM = 5 // AM or PM after numeric + S_ALPHA = 6 + S_DASH = 7 // - + s_WHITESPACE = 8 +) + +/* + features = []uint8{ + + } + + +*/ +type Features []TimeFeature + +func (f Features) Has(ask TimeFeature) bool { + return f[ask] == ask +} + +func (f Features) ParseString() string { + return "" +} + +type TimeFeature uint8 + +const ( + ALL_NUMERIC TimeFeature = 0 + STARTS_ALPHA TimeFeature = 1 + STARTS_NUMERIC TimeFeature = 2 + HAS_NUMERIC TimeFeature = 3 + HAS_ALPHA TimeFeature = 4 + HAS_WHITESPACE TimeFeature = 5 + HAS_COMMA TimeFeature = 6 + HAS_SLASH TimeFeature = 7 + HAS_DASH TimeFeature = 8 + HAS_Z TimeFeature = 9 + HAS_T TimeFeature = 10 + HAS_COLON TimeFeature = 11 + HAS_AMPM TimeFeature = 12 +) + +func parseFeatures(datestr string) Features { + features := make(Features, 20) + // totalLen := len(datestr) + // switch { + // case totalLen < 4: + // u.Debug("len < 4") + // } + + // if unicode.IsLetter(datestr[0]) { + // features = append(FEAUTURES, STARTS_ALPHA) + // } + + var lexeme string + state := S_START + //prevState := S_START + next := int32(datestr[0]) + //prev := int32(datestr[0]) + for i := 0; i < len(datestr); i++ { + char := int32(datestr[i]) + if i+1 < len(datestr) { + next = int32(datestr[i+1]) + //u.Debugf("set next: %s", string(next)) + } + switch char { + case ' ', '\n', '\t': + features[HAS_WHITESPACE] = HAS_WHITESPACE + case ',': + features[HAS_COMMA] = HAS_COMMA + case '-': + features[HAS_DASH] = HAS_DASH + case ':': + features[HAS_COLON] = HAS_COLON + case '/': + features[HAS_SLASH] = HAS_SLASH + case 'Z': + features[HAS_Z] = HAS_Z + case 'T': + features[HAS_T] = HAS_T + case 'A', 'P': + if next == 'M' { + u.Info("Found feature AMPM") + features[HAS_AMPM] = HAS_AMPM + } + } + switch state { + case S_START: + lexeme = lexeme + string(char) + if unicode.IsLetter(char) { + state = S_ALPHA + features[STARTS_ALPHA] = STARTS_ALPHA + features[HAS_ALPHA] = HAS_ALPHA + } else if unicode.IsNumber(char) { + state = S_NUMERIC + features[STARTS_NUMERIC] = STARTS_NUMERIC + features[HAS_NUMERIC] = HAS_NUMERIC + } else if char == ' ' { + //u.Info("is whitespace") + state = s_WHITESPACE + } else { + u.Error("unrecognized input? ", char, " ", string(char)) + } + case S_ALPHA: + if unicode.IsLetter(char) { + features[STARTS_ALPHA] = STARTS_ALPHA + features[HAS_ALPHA] = HAS_ALPHA + } else if unicode.IsNumber(char) { + state = S_NUMERIC + features[STARTS_NUMERIC] = STARTS_NUMERIC + features[HAS_NUMERIC] = HAS_NUMERIC + } else if char == ' ' { + //u.Info("is whitespace") + state = s_WHITESPACE + } else { + u.Error("unrecognized input? ", char, " ", string(char)) + } + lexeme = lexeme + string(char) + case S_NUMERIC: + if unicode.IsLetter(char) { + features[HAS_ALPHA] = HAS_ALPHA + } else if unicode.IsNumber(char) { + features[HAS_NUMERIC] = HAS_NUMERIC + } else if char == ' ' { + u.Info("is whitespace") + state = s_WHITESPACE + } else { + u.Error("unrecognized input? ", char, " ", string(char)) + } + lexeme = lexeme + string(char) + } + //prev = char + } + + return features +} + +// Given an unknown date format, detect the type, parse, return time +func ParseAny(datestr string) (time.Time, error) { + f := parseFeatures(datestr) + switch { + case f.Has(HAS_DASH) && !f.Has(HAS_SLASH): + switch { + case f.Has(HAS_WHITESPACE) && f.Has(HAS_COLON): + //2006-01-02 15:04:05.000 + case f.Has(HAS_WHITESPACE) && f.Has(HAS_COLON): + //2006-01-02 + //2006-01-02 + } + case f.Has(HAS_SLASH): + switch { + case f.Has(HAS_WHITESPACE) && f.Has(HAS_COLON): + // 03/03/2012 10:11:59 + // 3/1/2012 10:11:59 + u.Debugf("trying format: 3/1/2012 10:11:59 ") + //May 8, 2009 5:57:51 PM 2006-01-02 15:04:05.000 + if t, err := time.Parse("01/02/2006 15:04:05", datestr); err == nil { + return t, nil + } else { + if t, err := time.Parse("1/2/2006 15:04:05", datestr); err == nil { + return t, nil + } else { + u.Error(err) + } + } + case !f.Has(HAS_SLASH): + // 3/1/2014 + // 10/13/2014 + // 01/02/2006 + } + case f.Has(HAS_ALPHA) && f.Has(HAS_COMMA): + switch { + case f.Has(HAS_AMPM): + u.Debugf("trying format: 2006-01-02 15:04:05 PM ") + //May 8, 2009 5:57:51 PM 2006-01-02 15:04:05.000 + if t, err := time.Parse("Jan 2, 2006 3:04:05 PM", datestr); err == nil { + return t, nil + } else { + u.Error(err) + } + } + default: + u.Errorf("Could not find format: %s", datestr) + } + return time.Now(), fmt.Errorf("Not found: %s", datestr) +} + +// Given an unknown date format, detect the type and return +// the +func FindParseFormat(datestr string) (string, error) { + + return "", fmt.Errorf("Not recognized: %s", datestr) +} diff --git a/parseany_test.go b/parseany_test.go new file mode 100644 index 0000000..ec4592f --- /dev/null +++ b/parseany_test.go @@ -0,0 +1,64 @@ +package dateparse + +import ( + u "github.com/araddon/gou" + "github.com/bmizerany/assert" + "testing" + "time" +) + +var _ = time.April + +/* + ANSIC = "Mon Jan _2 15:04:05 2006" + UnixDate = "Mon Jan _2 15:04:05 MST 2006" + RubyDate = "Mon Jan 02 15:04:05 -0700 2006" + RFC822 = "02 Jan 06 15:04 MST" + RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone + RFC850 = "Monday, 02-Jan-06 15:04:05 MST" + RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST" + RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone + RFC3339 = "2006-01-02T15:04:05Z07:00" + RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" + Kitchen = "3:04PM" + // Handy time stamps. + Stamp = "Jan _2 15:04:05" + StampMilli = "Jan _2 15:04:05.000" + StampMicro = "Jan _2 15:04:05.000000" + StampNano = "Jan _2 15:04:05.000000000" + + // unix etc + 1398045032 time.Now().Unix() + 1398045078199135196 time.Now().UnixNano() + + // Others + "May 8, 2009 5:57:51 PM" + + + Apr 7, 2014 4:58:55 PM + 03/19/2012 10:11:59 + 3/1/2014 + 10/13/2014 + 01/02/2006 + + 2016-03-14 00:00:00.000 + 2006-01-02 + +*/ + +func init() { + u.SetupLogging("debug") +} + +func TestParse(t *testing.T) { + //f := parseFeatures("May 8, 2009 5:57:51 PM") + ts, _ := ParseAny("May 8, 2009 5:57:51 PM") + //u.Debug(" ", ts.Unix()) + //u.Debugf("%v", f) + //u.Debugf("%v", ts) + assert.T(t, ts.Unix() == 1241805471) + ts, _ = ParseAny("03/19/2012 10:11:59") + u.Debug(ts.Unix(), ts) + assert.T(t, ts.Unix() == 1332151919) + +}