在“查询/过滤”的时候支持使用日期类型的数学表达式。表达式以“锚定”日期开始,该日期可以是现在,也可以是以“||”结尾的日期字符串。它后面可以是一个数学表达式,支持 +,- 和 /(四舍五入)。支持的单位有:
-
y (year)
-
M (month)
-
w (week)
-
d (day)
-
h (hour)
-
m (minute)
-
s (second)
ES 中的 Date Math。
常规示例
使用 DateMath 提供的静态方法:
1
| Expect("2020-01-23T00:00:00").WhenSerializing(Nest.DateMath.Anchored(new DateTime(2020,01, 23)));
|
字符串则会隐式转换为 DateMath
1
| Expect("now").WhenSerializing<Nest.DateMath>("now");
|
DateMath 对于入参会进行一定程度的容错:
1 2 3 4 5 6 7 8 9
| var nonsense = "now||*asdaqwe"; Expect(nonsense) .WhenSerializing<Nest.DateMath>(nonsense) .AssertSubject(dateMath => ((IDateMath)dateMath) .Anchor.Match( d => d.Should().NotBe(default(DateTime)), s => s.Should().Be(nonsense) ) );
|
DateTime 还会隐式转换为简单的日期数学表达式
1 2 3 4
| var date = new DateTime(2020,1, 23);
var utcDate = new DateTime(2020, 1, 23, 0, 0, 0, DateTimeKind.Utc);
|
复杂示例
范围可以链接到简单表达式
1 2 3 4
| Expect("now+1d").WhenSerializing(Nest.DateMath.Now.Add("1d"));
Expect("now+1d-1m").WhenSerializing( Nest.DateMath.Now.Add("1d").Subtract(TimeSpan.FromMinutes(1)));
|
经过四舍五入的表达式,之后不能再使用范围进行链接,如下:
1 2 3 4
| Expect("now+1d-1m/d").WhenSerializing( Nest.DateMath.Now.Add("1d") .Subtract(TimeSpan.FromMinutes(1)) .RoundTo(DateMathTimeUnit.Day));
|
锚定日期时,需要在锚点和范围之间使用分隔符 “||”。同样,可以链接多个范围
1 2 3 4
| Expect("2020-01-23T00:00:00||+1d-1m").WhenSerializing( Nest.DateMath.Anchored(new DateTime(2020,1,23)) .Add("1d") .Subtract(TimeSpan.FromMinutes(1)));
|
含有小数时间
Elasticsearch中的日期数学表达式不支持小数。
为了在 NEST 中更轻松地使用日期数学,从字符串,TimeSpan 和 double 转换而来的值会将小数部分转换为最大的整数值和单位,四舍五入到最接近的秒数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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)));
|
舍入
可以使用构造函数控制舍入,并传递一个值进行舍入:
1 2 3 4 5 6 7 8 9 10 11
| 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)));
|
相等性比较
DateMathTime 实现了 equality 和 comparison:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| 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();
|
年份和月份不包含确切值:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 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();
|