Skip to content

Commit 3555cfe

Browse files
authored
Merge pull request #113 from exceptionless/feature/datemath
Elasticsearch DateMath support
2 parents c27d430 + b74c5ea commit 3555cfe

File tree

11 files changed

+1918
-10
lines changed

11 files changed

+1918
-10
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,5 @@ _NCrunch_*
5151
# Rider auto-generates .iml files, and contentModel.xml
5252
**/.idea/**/*.iml
5353
**/.idea/**/contentModel.xml
54-
**/.idea/**/modules.xml
54+
**/.idea/**/modules.xml
55+
.idea/.idea.Exceptionless.DateTimeExtensions/.idea/

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"cSpell.words": [
3+
"millis",
34
"timespan"
45
]
56
}

README.md

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,101 @@ bool isDay = day.IsBusinessDay(date);
3434

3535
### DateTime Ranges
3636

37-
Quickly work with date ranges. . Check out our [unit tests](https://github.com/exceptionless/Exceptionless.DateTimeExtensions/blob/main/tests/Exceptionless.DateTimeExtensions.Tests/DateTimeRangeTests.cs) for more usage samples.
37+
Quickly work with date ranges with support for Elasticsearch-style date math expressions and bracket notation. Check out our [unit tests](https://github.com/exceptionless/Exceptionless.DateTimeExtensions/blob/main/tests/Exceptionless.DateTimeExtensions.Tests/DateTimeRangeTests.cs) for more usage samples.
3838

3939
```csharp
40+
// Basic range parsing
4041
var range = DateTimeRange.Parse("yesterday", DateTime.Now);
4142
if (range.Contains(DateTime.Now.Subtract(TimeSpan.FromHours(6)))) {
4243
//...
4344
}
45+
46+
// Elasticsearch Date Math support with proper timezone handling
47+
var elasticRange = DateTimeRange.Parse("2025-01-01T01:25:35Z||+3d/d", DateTime.Now);
48+
// Supports timezone-aware operations: Z (UTC), +05:00, -08:00
49+
50+
// Bracket notation support [start TO end]
51+
var bracketRange = DateTimeRange.Parse("[2023-01-01 TO 2023-12-31]", DateTime.Now);
52+
53+
// Wildcard support for open-ended ranges
54+
var wildcardRange = DateTimeRange.Parse("[2023-01-01 TO *]", DateTime.Now); // From date to infinity
4455
```
4556

57+
#### Date Math Features
58+
59+
Supports full Elasticsearch date math syntax following [official specifications](https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#date-math):
60+
61+
- **Anchors**: `now`, explicit dates with `||` separator
62+
- **Operations**: `+1d` (add), `-1h` (subtract), `/d` (round down)
63+
- **Units**: `y` (years), `M` (months), `w` (weeks), `d` (days), `h`/`H` (hours), `m` (minutes), `s` (seconds)
64+
- **Timezone Support**: Preserves explicit timezones (`Z`, `+05:00`, `-08:00`) or uses system timezone as fallback
65+
66+
Examples:
67+
68+
- `now+1h` - One hour from now
69+
- `now-1d/d` - Start of yesterday
70+
- `2025-01-01T01:25:35Z||+3d/d` - January 4th, 2025 (start of day) in UTC
71+
- `2023-06-15T14:30:00+05:00||+1M-2d` - One month minus 2 days from the specified date/time in +05:00 timezone
72+
73+
### DateMath Utility
74+
75+
For applications that need standalone date math parsing without the range functionality, the `DateMath` utility class provides direct access to Elasticsearch date math expression parsing. Check out our [unit tests](https://github.com/exceptionless/Exceptionless.DateTimeExtensions/blob/main/tests/Exceptionless.DateTimeExtensions.Tests/DateMathTests.cs) for more usage samples.
76+
77+
```csharp
78+
using Exceptionless.DateTimeExtensions;
79+
80+
// Parse date math expressions with standard .NET conventions
81+
var baseTime = DateTimeOffset.Now;
82+
83+
// Parse method - throws ArgumentException on invalid input
84+
var result = DateMath.Parse("now+1h", baseTime);
85+
var rounded = DateMath.Parse("now-1d/d", baseTime, isUpperLimit: false); // Start of yesterday
86+
87+
// TryParse method - returns bool for success/failure
88+
if (DateMath.TryParse("2023.06.15||+1M/d", baseTime, false, out var parsed)) {
89+
// Successfully parsed: June 15, 2023 + 1 month, rounded to start of day
90+
Console.WriteLine($"Parsed: {parsed:O}");
91+
}
92+
93+
// Upper limit behavior affects rounding
94+
var startOfDay = DateMath.Parse("now/d", baseTime, isUpperLimit: false); // 00:00:00
95+
var endOfDay = DateMath.Parse("now/d", baseTime, isUpperLimit: true); // 23:59:59.999
96+
97+
// Explicit dates with timezone preservation
98+
var utcResult = DateMath.Parse("2025-01-01T01:25:35Z||+3d/d", baseTime);
99+
var offsetResult = DateMath.Parse("2023-06-15T14:30:00+05:00||+1M", baseTime);
100+
```
101+
102+
#### TimeZone-Aware DateMath
103+
104+
The `DateMath` utility also provides overloads that work directly with `TimeZoneInfo` for better timezone handling:
105+
106+
```csharp
107+
using Exceptionless.DateTimeExtensions;
108+
109+
// Parse expressions using a specific timezone
110+
var utcTimeZone = TimeZoneInfo.Utc;
111+
var easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("US/Eastern");
112+
113+
// "now" will use current time in the specified timezone
114+
var utcResult = DateMath.Parse("now+1h", utcTimeZone);
115+
var easternResult = DateMath.Parse("now/d", easternTimeZone, isUpperLimit: false);
116+
117+
// TryParse with timezone
118+
if (DateMath.TryParse("now+2d-3h", easternTimeZone, false, out var result)) {
119+
Console.WriteLine($"Eastern time result: {result:O}");
120+
}
121+
122+
// Dates without explicit timezone use the provided TimeZoneInfo
123+
var localDate = DateMath.Parse("2023-06-15T14:30:00||+1M", easternTimeZone);
124+
125+
// Dates with explicit timezone are preserved regardless of TimeZoneInfo parameter
126+
var preservedTz = DateMath.Parse("2023-06-15T14:30:00+05:00||+1M", easternTimeZone);
127+
// Result will still have +05:00 offset, not Eastern time offset
128+
```
129+
130+
The `DateMath` utility supports the same comprehensive syntax as `DateTimeRange` but provides a simpler API for direct parsing operations.
131+
46132
### TimeUnit
47133

48134
Quickly work with time units. . Check out our [unit tests](https://github.com/exceptionless/Exceptionless.DateTimeExtensions/blob/main/tests/Exceptionless.DateTimeExtensions.Tests/TimeUnitTests.cs) for more usage samples.

0 commit comments

Comments
 (0)