New

The executive guide to generative AI

Read more
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

Date math expressions

edit

The date type supports using date math expression when using it in a query/filter Whenever durations need to be specified, eg for a timeout parameter, the duration can be specified

The expression starts with an "anchor" date, which can be either now or a date string (in the applicable format) ending with ||. It can be followed by a math expression, supporting +, - and / (rounding). The units supported are

  • y (year)
  • M (month)
  • w (week)
  • d (day)
  • h (hour)
  • m (minute)
  • s (second)

Be sure to read the Elasticsearch documentation on Date Math.

Simple expressions

edit

You can create simple expressions using any of the static methods on DateMath

Expect("2015-05-05T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2015,05, 05)));

strings implicitly convert to DateMath

Expect("now").WhenSerializing<Nest.DateMath>("now");

but are lenient to bad math expressions

var nonsense = "now||*asdaqwe";

the resulting date math will assume the whole string is the anchor

Expect(nonsense)
    .WhenSerializing<Nest.DateMath>(nonsense)
    .AssertSubject(dateMath => ((IDateMath)dateMath)
        .Anchor.Match(
            d => d.Should().NotBe(default(DateTime)),
            s => s.Should().Be(nonsense)
        )
    );

DateTime also implicitly convert to simple date math expressions; the resulting anchor will be an actual DateTime, even after a serialization/deserialization round trip

var date = new DateTime(2015, 05, 05);

will serialize to

"2015-05-05T00:00:00"

When the DateTime is local or UTC, the time zone information is included. For example, for a UTC DateTime

var utcDate = new DateTime(2015, 05, 05, 0, 0, 0, DateTimeKind.Utc);

will serialize to

"2015-05-05T00:00:00Z"

Complex expressions

edit

Ranges can be chained on to simple expressions

Expect("now+1d").WhenSerializing(
    Nest.DateMath.Now.Add("1d"));

Including multiple operations

Expect("now+1d-1m").WhenSerializing(
    Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)));

A rounding value can be chained to the end of the expression, after which no more ranges can be appended

Expect("now+1d-1m/d").WhenSerializing(
    Nest.DateMath.Now.Add("1d")
        .Subtract(TimeSpan.FromMinutes(1))
        .RoundTo(DateMathTimeUnit.Day));

When anchoring dates, a || needs to be appended as clear separator between the anchor and ranges. Again, multiple ranges can be chained

Expect("2015-05-05T00:00:00||+1d-1m").WhenSerializing(
    Nest.DateMath.Anchored(new DateTime(2015,05,05))
        .Add("1d")
        .Subtract(TimeSpan.FromMinutes(1)));

Fractional times

edit

Date math expressions within Elasticsearch do not support fractional numbers. To make working with Date math easier within NEST, conversions from string, TimeSpan and double will convert a fractional value to the largest whole number value and unit, rounded to the nearest second.

Expect("now+1w").WhenSerializing(Nest.DateMath.Now.Add(TimeSpan.FromDays(7)));

Expect("now+1w").WhenSerializing(Nest.DateMath.Now.Add("1w"));

Expect("now+1w").WhenSerializing(Nest.DateMath.Now.Add(604800000));

Expect("now+7d").WhenSerializing(Nest.DateMath.Now.Add("7d"));

Expect("now+30h").WhenSerializing(Nest.DateMath.Now.Add(TimeSpan.FromHours(30)));

Expect("now+30h").WhenSerializing(Nest.DateMath.Now.Add("1.25d"));

Expect("now+90001s").WhenSerializing(
    Nest.DateMath.Now.Add(TimeSpan.FromHours(25).Add(TimeSpan.FromSeconds(1))));

Expect("now+90000s").WhenSerializing(
    Nest.DateMath.Now.Add(TimeSpan.FromHours(25).Add(TimeSpan.FromMilliseconds(1))));

Expect("now+1y").WhenSerializing(Nest.DateMath.Now.Add("1y"));

Expect("now+12M").WhenSerializing(Nest.DateMath.Now.Add("12M"));

Expect("now+18M").WhenSerializing(Nest.DateMath.Now.Add("1.5y"));

Expect("now+52w").WhenSerializing(Nest.DateMath.Now.Add(TimeSpan.FromDays(7 * 52)));

Rounding

edit

Rounding can be controlled using the constructor, and passing a value for rounding

Expect("now+2s").WhenSerializing(
    Nest.DateMath.Now.Add(new DateMathTime("2.5s", MidpointRounding.ToEven)));

Expect("now+3s").WhenSerializing(
    Nest.DateMath.Now.Add(new DateMathTime("2.5s", MidpointRounding.AwayFromZero)));

Expect("now+0s").WhenSerializing(
    Nest.DateMath.Now.Add(new DateMathTime(500, MidpointRounding.ToEven)));

Expect("now+1s").WhenSerializing(
    Nest.DateMath.Now.Add(new DateMathTime(500, MidpointRounding.AwayFromZero)));

Equality and Comparisons

edit

DateMathTime supports implements equality and comparison

DateMathTime twoSeconds = new DateMathTime(2, DateMathTimeUnit.Second);
DateMathTime twoSecondsFromString = "2s";
DateMathTime twoSecondsFromTimeSpan = TimeSpan.FromSeconds(2);
DateMathTime twoSecondsFromDouble = 2000;

twoSeconds.Should().Be(twoSecondsFromString);
twoSeconds.Should().Be(twoSecondsFromTimeSpan);
twoSeconds.Should().Be(twoSecondsFromDouble);

DateMathTime threeSecondsFromString = "3s";
DateMathTime oneMinuteFromTimeSpan = TimeSpan.FromMinutes(1);

(threeSecondsFromString > twoSecondsFromString).Should().BeTrue();
(oneMinuteFromTimeSpan > threeSecondsFromString).Should().BeTrue();

Since years and months do not contain exact values

  • A year is approximated to 365 days
  • A month is approximated to (365 / 12) days
DateMathTime oneYear = new DateMathTime(1, DateMathTimeUnit.Year);
DateMathTime oneYearFromString = "1y";
DateMathTime twelveMonths = new DateMathTime(12, DateMathTimeUnit.Month);
DateMathTime twelveMonthsFromString = "12M";

oneYear.Should().Be(oneYearFromString);
oneYear.Should().Be(twelveMonths);
twelveMonths.Should().Be(twelveMonthsFromString);

DateMathTime thirteenMonths = new DateMathTime(13, DateMathTimeUnit.Month);
DateMathTime thirteenMonthsFromString = "13M";
DateMathTime fiftyTwoWeeks = "52w";

(oneYear < thirteenMonths).Should().BeTrue();
(oneYear < thirteenMonthsFromString).Should().BeTrue();
(twelveMonths > fiftyTwoWeeks).Should().BeTrue();
(oneYear > fiftyTwoWeeks).Should().BeTrue();
Was this helpful?
Feedback