A natural language date/time parser with pluggable rules

Overview

when godoc wercker status

when is a natural language date/time parser with pluggable rules and merge strategies

Examples

  • tonight at 11:10 pm
  • at Friday afternoon
  • the deadline is next tuesday 14:00
  • drop me a line next wednesday at 2:25 p.m
  • it could be done at 11 am past tuesday

Check EN, RU and BR rules and tests for them, for more examples.

Needed rule not found? Open an issue with the case and it will be added asap.

How it works

Usually, there are several rules added to the parser's instance for checking. Each rule has its own borders - length and offset in provided string. Meanwhile, each rule yields only the first match over the string. So, the library checks all the rules and extracts a cluster of matched rules which have distance between each other less or equal to options.Distance, which is 5 by default. For example:

on next wednesday at 2:25 p.m.
   └──────┬─────┘    └───┬───┘
       weekday      hour + minute

So, we have a cluster of matched rules - "next wednesday at 2:25 p.m." in the string representation.

After that, each rule is applied to the context. In order of definition or in match order, if options.MatchByOrder is set to true(which it is by default). Each rule could be applied with given merge strategy. By default, it's an Override strategy. The other strategies are not implemented yet in the rules. Pull requests are welcome.

Usage

w := when.New(nil)
w.Add(en.All...)
w.Add(common.All...)

text := "drop me a line in next wednesday at 2:25 p.m"
r, err := w.Parse(text, time.Now())
if err != nil {
	// an error has occurred
}
if  r == nil {
 	// no matches found
}

fmt.Println(
	"the time",
	r.Time.String(),
	"mentioned in",
	text[r.Index:r.Index+len(r.Text)],
)

Distance Option

w := when.New(nil)
w.Add(en.All...)
w.Add(common.All...)

text := "February 23, 2019 | 1:46pm"

// With default distance (5):
// February 23, 2019 | 1:46pm
//            └───┬───┘
//           distance: 9 (1:46pm will be ignored)

r, _ := w.Parse(text, time.Now())
fmt.Printf(r.Time.String())
// "2019-02-23 09:21:21.835182427 -0300 -03"
// 2019-02-23 (correct)
//   09:21:21 ("wrong")

// With custom distance (10):
w.SetOptions(&rules.Options{
	Distance:     10,
	MatchByOrder: true})

r, _ = w.Parse(text, time.Now())
fmt.Printf(r.Time.String())
// "2019-02-23 13:46:21.559521554 -0300 -03"
// 2019-02-23 (correct)
//   13:46:21 (correct)

State of the project

The project is in a more-or-less complete state. It's used for one project already. Bugs will be fixed as soon as they will be found.

TODO

  • readme: describe all the existing rules
  • implement missed rules for these examples
  • add cli and simple rest api server(#2)

LICENSE

http://www.apache.org/licenses/LICENSE-2.0

Comments
  • Ability to use a different timezone?

    Ability to use a different timezone?

    I couldn't see to find any timezone parsing code. So, for example, if I am saying "10 PM EST" while the machine's local time is in PST then I expect 7 PM as the outcome in local time or 10 PM with the timezone information extracted.

    opened by ashishb 2
  • Truncate

    Truncate "10pm" to "10:00:00" as opposed to "10:00:12" (current second)

    Thanks for the great library. I have no illusions of this getting merged (since the lib seems unmaintained by now), but this annoyed me enough to create a PR :-)

    Currently "10pm" is expanded to "10:00:x" with x being the current second. So if it's 8:23:12pm right now and you say "10pm", it'll be "10:00:12", which is not really what the user expects.

    I forked it and made keep this small change in a tag. You can use it like this:

    replace github.com/olebedev/when => github.com/binwiederhier/when v0.0.1-binwiederhier2
    
    opened by binwiederhier 1
  • Added simple parse exact month date for ru langugage

    Added simple parse exact month date for ru langugage

    First of all, thanks for the package, i have my own solution, but it more hardcoded:)

    I do not pretend to be the best solution, but it seemed to me necessary to add the simplest definition of the number along with the month

    And i think it needs ignore idea folder and go fmt code :)

    BTW, what about naming? Why you use SNAKE_CASE instead CamelCase? What about rename them all?

    opened by temamagic 1
  • Add past time rules: T ago

    Add past time rules: T ago

    This adds english rules for writing "T ago". The commit means that the following examples should work:

    5 minutes ago 2 hours ago a month ago half a month ago etc.

    It does not cover more complex rules such as "1 year ago tomorrow".

    Let me know if there is anything that needs updating.

    Thanks!

    opened by antonlindstrom 1
  • bias ExactMonthDate towards future dates

    bias ExactMonthDate towards future dates

    Hi! I picked up when in a quick project to file tasks into notion, and it's been great so far! I'm glad I don't have to rewrite all of this natural time parsing myself. Being the end of the year, I've been trying to schedule tasks for next January when I go back to work, and was surprised when they were parsed as January of 2021 instead of 2022.

    I was wondering:

    • Is it intentional that ExactMonthDate parses, e.g. January 4th as 2021-01-04 instead of 2022-01-04?
    • If not, would it be possible to bias ExactMonthDate the next occurrence of the date? This is a breaking change to the library, so I understand if it's not acceptable to upstream.

    I do have a working approach (that isn't particularly well thought out :grin:) which I could turn over to a pull request if y'all are interested.

    Thanks!

    opened by crockeo 1
  • Is it possible to have 'deadlines' extended to work without 'in/within'

    Is it possible to have 'deadlines' extended to work without 'in/within'

    It would be nice to be able to parse "2 hours" or "4 days" instead of requiring the in/within, maybe it's a bit "noisy" but if it were possible via an option or some sort of "aggressive" version of deadline i think it could be nice - sometimes you just want to parse a time no matter what, and it won't always have the in/within at the start

    opened by smt923 0
  • Dependent dates

    Dependent dates

    when cannot parse dates with relative delta from some date:

    gore> r, err := w.Parse("завтра в 12:00 поезд, напомни за час", time.Now())
    &when.Result{
      Index:  0,
      Text:   "завтра в 12:00",
      Source: "завтра в 12:00 поезд, напомни за час",
      Time:   2019-02-28 12:00:28 Local,
    }
    nil
    

    BTW, I have old rutimeparser lib for Python. Maybe, some test cases will be useful for you.

    opened by orsinium 2
Owner
Oleg Lebedev
Don’t let the Canva bugs bite
Oleg Lebedev
:clock1: Date and Time - Golang Formatting Library

Kair Date and Time - Golang Formatting Library Setup To get Kair > Go CLI go get github.com/GuilhermeCaruso/kair > Go DEP dep ensure -add github.com/G

Guilherme Caruso 24 Sep 26, 2022
Time struct in Go that uses 4 bytes of memory vs the 24 bytes of time.Time

A tiny time object in Go. Tinytime uses 4 bytes of memory vs the 24 bytes of a standard time.Time{}

Lane Wagner 59 Oct 3, 2022
GoLang Parse many date strings without knowing format in advance.

Go Date Parser Parse many date strings without knowing format in advance. Uses a scanner to read bytes and use a state machine to find format. Much fa

Aaron Raddon 1.8k Dec 31, 2022
Go-timeparser - Flexible Time Parser for Golang

go-timeparser Flexible Time Parser for Golang Installation Download timeparser w

Kazuaki Yamamoto 2 Dec 29, 2022
Carbon for Golang, an extension for Time

Carbon A simple extension for Time based on PHP's Carbon library. Features: Time is embedded into Carbon (provides access to all of Time's functionali

Uniplaces LTD 742 Dec 20, 2022
:clock8: Better time duration formatting in Go!

durafmt durafmt is a tiny Go library that formats time.Duration strings (and types) into a human readable format. go get github.com/hako/durafmt Why

Wesley Hill 453 Dec 16, 2022
Now is a time toolkit for golang

Now Now is a time toolkit for golang Install go get -u github.com/jinzhu/now Usage Calculating time based on current time import "github.com/jinzhu/n

Jinzhu 4k Dec 23, 2022
Golang package to manipulate time intervals.

timespan timespan is a Go library for interacting with intervals of time, defined as a start time and a duration. Documentation API Installation Insta

null 82 Sep 26, 2022
timeutil - useful extensions (Timedelta, Strftime, ...) to the golang's time package

timeutil - useful extensions to the golang's time package timeutil provides useful extensions (Timedelta, Strftime, ...) to the golang's time package.

Kyoung-chan Lee 190 Dec 22, 2022
Go time library inspired by Moment.js

Goment Current Version: 1.4.0 Changelog Goment is a port of the popular Javascript datetime library Moment.js. It follows the Moment.js API closely, w

Nick Leeper 209 Dec 24, 2022
fasttime - fast time formatting for go

fasttime - fast time formatting for go

phuslu 67 Dec 13, 2022
🌐 A time zone helper

?? A time zone helper tz helps you schedule things across time zones. It is an interactive TUI program that displays time across a few time zones of y

Arnaud Berthomier 703 Dec 29, 2022
Clock is a small library for mocking time in Go.

clock Clock is a small library for mocking time in Go. It provides an interface around the standard library's time package so that the application can

Ben Johnson 606 Dec 30, 2022
Copy of stdlib's time.Duration, but ParseDuration accepts other bigger units such as days, weeks, months and years

duration Copy of stdlib's time.Duration, but ParseDuration accepts other units as well: d: days (7 * 24 * time.Hour) w: weeks (7 * Day) mo: months (30

Carlos Alexandro Becker 11 Jun 21, 2022
time format golang

a simple plugin to change date and time format

Ibnu Surkati 2 Sep 29, 2021
Structural time package for jalali calendar

Jalali Structural time package for jalali calendar. This package support parse from string, json and time. Structures There are three data structures

Bardo Go Framework 1 Mar 21, 2022
Show time by timezone

Show time by timezone

Michael Bruskov 1 Jan 22, 2022
Timediff is a Go package for printing human readable, relative time differences 🕰️

timediff is a Go package for printing human readable, relative time differences. Output is based on ranges defined in the Day.js JavaScript library, and can be customized if needed.

MergeStat 289 Dec 25, 2022
A natural language date/time parser with pluggable rules

when when is a natural language date/time parser with pluggable rules and merge strategies Examples tonight at 11:10 pm at Friday afternoon the deadli

Oleg Lebedev 1.2k Dec 26, 2022
Natural-deploy - A natural and simple way to deploy workloads or anything on other machines.

Natural Deploy Its Go way of doing Ansibles: Motivation: Have you ever felt when using ansible or any declarative type of program that is used for dep

Akilan Selvacoumar 0 Jan 3, 2022