Coder Social home page Coder Social logo

naturaltimeparser's Introduction

Pathoschild.NaturalTimeParser implements part of the GNU date input format. It lets you use date math with natural date strings (like DateTime.Now.Offset("+5 days 14 hours -2 minutes")), and will eventually support creating dates from natural time formats (like "last month +2 days"). The parser can be used by itself, or integrated with a templating engine like DotLiquid or SmartFormat.NET (see details below).

This is used in at least one production system, so it's reasonably robust. Contributions to further develop the library are welcome.

Usage

Download the Pathoschild.NaturalTimeParser NuGet package and reference the Pathoschild.NaturalTimeParser namespace. This lets you apply a natural offset to a date:

   // both lines are equivalent
   DateTime result = DateTime.Now.Offset("2 years ago");
   DateTime result = TimeParser.Default.Parse("2 years ago");

Relative time units (date arithmetic)

The parser has full support for relative time units. For example, the following formats are supported:

  • 1 year ago
  • -2 years
  • 16 fortnights
  • -1 year ago (next year)

You can also chain relative units:

  • 1 year 2 months (14 months from now)
  • 1 year -2 fortnights (almost 11 months from now)
  • 1 year ago 1 year (today; equivalent to -1 year +1 year)

Integrated with template engines

DotLiquid

The parser is available as a plugin for DotLiquid through the Pathoschild.NaturalTimeParser.DotLiquid NuGet package. DotLiquid is a safe templating library that lets you format strings with token replacement, basic logic, and text transforms. For example, this lets us format messages like this:

   Template.RegisterFilter(typeof(NaturalDateFilter));
   string message = "Your trial will expire in 30 days (on {{ 'today' | as_date | date_offset:'30 days' | date:'yyyy-MM-dd' }}).";
   message = Template.Parse(message).Render(); // "Your trial will expire in 30 days (on 2013-06-01)."

The plugin adds four custom tokens ({Today}/{TodayUTC} for the current local/UTC date, and {Now}/{NowUTC} for the current local/UTC date & time) and adds support for applying relative time units to any date. For example, you can format an arbitrary date token:

   Template.RegisterFilter(typeof(NaturalDateFilter));
   string message = "Your trial will expire in a long time (on {{ expiry_date | date_offset:'30 days' | date:'yyyy-MM-dd' }}).";
   message = Template.Parse(message).Render(Hash.FromAnonymousObject(new { ExpiryDate = new DateTime(2050, 01, 01) } }); // "Your trial will expire in a long time (on 2050-01-31)."
SmartFormat

The parser is available as a plugin for SmartFormat.NET through the Pathoschild.NaturalTimeParser.SmartFormat NuGet package. SmartFormat is a string composition library that enables advanced token replacement. For example, this lets us format messages like this:

   SmartFormatter formatter = Smart.CreateDefaultSmartFormat().AddExtensionsForNaturalTime();
   string message = "Your trial will expire in 30 days (on {Today:yyyy-MM-dd|+30 days}).";
   message = formatter.Format(message); // "Your trial will expire in 30 days (on 2013-06-01).";

The plugin adds four custom tokens ({Today}/{TodayUTC} for the current local/UTC date, and {Now}/{NowUTC} for the current local/UTC date & time) and adds support for applying relative time units to any date. For example, you can format an arbitrary date token:

   SmartFormatter formatter = Smart.CreateDefaultSmartFormat().AddExtensionsForNaturalTime();
   string message = "Your trial will expire in a long time (on {ExpiryDate:yyyy-MM-dd|+30 days}).";
   message = formatter.Format(message, new { ExpiryDate = new DateTime(2050, 01, 01) }); // "Your trial will expire in a long time (on 2050-01-31).";

Extending the parser

Localization

The default implementation is English but can support other languages. For example, you can enable relative time units in French:

   // configure French units
   ArithmeticTimePlugin plugin = TimeParser.Default.Parsers.OfType<ArithmeticTimePlugin>().First();
   plugin.SupportedUnits["jour"] = ArithmeticTimePlugin.RelativeTimeUnit.Days;
   plugin.SupportedUnits["heure"] = ArithmeticTimePlugin.RelativeTimeUnit.Hours;

   // now you can use French
   DateTime.Now.Offset("3 jours 4 heures");

Plugins

This is implemented as a simple plugin-based lexer, which breaks down an input string into its constituent tokens. For example, the string "yesterday +1 day" can be broken down into two tokens:

   [
      ["yesterday"],
      ["days", 1]
   ]

The parsing is provided by a set of plugins which implement IParseTimeStrings or IApplyTimeTokens:

  • IParseTimeStrings plugins are called to tokenize the input string. Each plugin scans the front of the string for recognized tokens, and stops at the first unrecognized value. Each matched token is stripped, and this is repeated until the entire string has been tokenized, or a portion is not recognized by any of the plugins (in which case a TimeParseFormatException is thrown).
  • IApplyTimeTokens plugins are called to apply a token to a date. For example, the ArithmeticTimePlugin applies a token like +3 days by returning date.AddDays(3).

New plugins can be added easily:

  TimeParser parser = new TimeParser(); // or TimeParser.Default
  parser.Parsers.Add(new SomePlugin());
  parser.Applicators.Add(new SomePlugin());

naturaltimeparser's People

Contributors

pathoschild avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

naturaltimeparser's Issues

The following test fails: Formatter_BuildsExpectedOutput("{Date:|10 years 2 months 3 days}")

Test Name: Formatter_BuildsExpectedOutput("{Date:|10 years 2 months 3 days}")
Test FullName: Pathoschild.NaturalTimeParser.Tests.Extensions.SmartFormattingTests.Formatter_BuildsExpectedOutput("{Date:|10 years 2 months 3 days}")
Test Source: c:\github\ramiabughazaleh\NaturalTimeParser\Tests\Extensions\SmartFormattingTests.cs : line 43
Test Outcome: Failed
Test Duration: 0:00:00.034

Result Message:
Expected string length 19 but was 20. Strings differ at index 0.
Expected: "2010-03-04 00:00:00"
But was: "3/4/2010 12:00:00 AM"
-----------^

Support parsing date time strings

I'd like TimeParser to be able to parse date time strings that have already been created by calling DateTime.ToString().

For example,

TimeParser timeParser = new TimeParser();
DateTime dateTime = DateTime.UtcNow;
string dateTimeAsString = dateTime.ToString(CultureInfo.InvariantCulture);
DateTime parsedDateTime = timeParser.Parse(dateTimeAsString);
Assert.AreEqual(dateTime, parsedDateTime);

Thank you.

Support parsing spelled out numerals

I'd like TimeParser to support parsing spelled out numerals.

For example, "two years ago" should be parsed the same as "2 years ago".

Thank you.

Consolidate tokens that end with "utc" by passing the expected DateTime in the constructor of the TimeParser class for example

I would like to consolidate the "now", "nowutc", "today", and "todayutc" tokens to just "now" and "today".

The expected type of DateTime can be passed in the constructor of the TimeParser class for example.

The parameter passed to the constructor can maybe be DateTime, DateTimeOffset, or DateTimeKind, for example but I'm not exactly sure which one is best.

In this way, then maybe the methods ParseName and Parse can also be consolidated into just one Parse(string input) method.

Thank you.

Parsing "{{ 'nowutc' | as_date | date_offset:'1 day' | date:'yyyy-MM-ddT00:00:00Z' }}" returns today's date instead of tomorrow's date

Hi.

Parsing {{ 'nowutc' | as_date | date_offset:'1 day' | date:'yyyy-MM-ddT00:00:00Z' }} returns today's date instead of tomorrow's date.

My current time zone is PDT = GMT - 7 (DST)
My current date and time is 5/30/2019 2:30 PM.

The date and time in GMT is 5/30/2019 9:30 PM.

So I expected parsing {{ 'nowutc' | as_date | date_offset:'1 day' | date:'yyyy-MM-ddT00:00:00Z' }} to return 5/31/2019, but it actually returns 5/30/2019.

Any ideas?

Thank you.

Support parsing "1 year from today"

I'd like to request being able to parse "1 year from today".

For example, if today's UTC date is "2017-01-21", then "1 year from todayutc" will result in "2018-01-21 12:00:00 AM".

Thank you.

Support "and" in ArithmeticTimePlugin to behave like "+" sign

Thank you for NaturalTimeParser 0.2.0.0.

I would like to be able to use "and" instead of the "+" plus sign when describing a specific date/time.

For example, "1 year ago and 5 days ago" should be parsed the same as "1 year ago + 5 days ago".

Thank you!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.