欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

NEST 中的日期数学表达式

程序员文章站 2022-03-18 14:32:22
Date math expressions Version: 5.x 英文原文地址: "Date math expressions" query/filter 中涉及到日期类型时(如: 参数),Elasticsearch 允许我们使用日期数学表达式。 表达式由一个 "anchor" (锚点)日期开头 ......

Date math expressions

Version: 5.x

英文原文地址:Date math expressions

query/filter 中涉及到日期类型时(如:timeout 参数),Elasticsearch 允许我们使用日期数学表达式。

表达式由一个 "anchor" (锚点)日期开头,这个锚点可以是 now 或者其他可用的以 || 结尾的日期格式字符串。锚点之后可以跟着一个数学表达式,支持 + , -/ (舍入取整)。可用的单位有:

  • y (year) 年
  • M (month) 月
  • w (week) 周
  • d (day) 日
  • h (hour) 时
  • m (minute) 分
  • s (second) 秒

单纯的一个整数表示以毫秒为单位的时间,2d 表示 2 天。

更多信息请参阅 Elasticsearch 官方文档中关于 Date Math 的说明。

说明:”锚点||数学表达式“ 所描述的其实就是一个参考日期 + 一个偏移时间。举个栗子:2018-01-01||+1d 表达的是 2018年1月2日

Simple expressions

你可以使用 DateMath 的静态方法创建一个简单的表达式

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

字符串会隐式转换成 DateMath

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

但是不会智能过滤错误的数学表达式

var nonsense = "now||*asdaqwe";

上面这个字符串转换成 DateMath 后会被当作一个锚点日期(没有数学表达式)

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

DateTime 也可以隐式转换成简单的日期数学表达式;生成的锚点是一个实际的 DateTime ,即使经过了往返过程中的序列化/反序列化

var date = new DateTime(2015, 05, 05);
Expect("2015-05-05T00:00:00").WhenSerializing<Nest.DateMath>(date)
    .Result(dateMath => ((IDateMath)dateMath)
        .Anchor.Match(
            d => d.Should().Be(date),
            s => s.Should().BeNull()
        )
    );

Complex expressions

可以将范围链接到简单表达式后面

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

可以链接多种操作

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

舍入值可以链接到表达式的末尾,在此之后不能追加其他范围

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

当设置一个锚点日期(参照日期),需要在定位点和范围之间插入一个分割符 || (自动地)。同样的,后面可以追加多个范围

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

DateMath 表达式不支持小数,所以会选择一个可以将表达式转换成整数的最大的单位

Expect("now+25h")
    .WhenSerializing(Nest.DateMath.Now.Add(TimeSpan.FromHours(25)))
    .WhenSerializing(Nest.DateMath.Now.Add(90000000))
    .WhenSerializing(Nest.DateMath.Now.Add(new Time(25, Nest.TimeUnit.Hour)))
    .WhenSerializing(Nest.DateMath.Now.Add("25h"));

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

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

Expect("now+1y")
    .WhenSerializing(Nest.DateMath.Now.Add("1y"))
    .WhenSerializing(Nest.DateMath.Now.Add(new Time(1, Nest.TimeUnit.Year)));

Expect("now+6M")
    .WhenSerializing(Nest.DateMath.Now.Add("6M"))
    .WhenSerializing(Nest.DateMath.Now.Add("0.5y"))
    .WhenSerializing(Nest.DateMath.Now.Add(new Time(0.5, Nest.TimeUnit.Year)))
    .WhenSerializing(Nest.DateMath.Now.Add(new Time(6, Nest.TimeUnit.Month)));

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

Expect("now+52w")
    .WhenSerializing(Nest.DateMath.Now.Add(new Time("52w")))
    .WhenSerializing(Nest.DateMath.Now.Add(new Time(52, Nest.TimeUnit.Week)));