DateTime / DateTimeOffset
Describes the possible expectations for DateTime and DateTimeOffset.
| Expectation | Negated | Summary |
|---|---|---|
IsEqualTo | IsNotEqualTo | equal to the expected value |
IsOneOf | IsNotOneOf | equal to one of the expected values |
IsAfter | IsNotAfter | later than the expected value |
IsOnOrAfter | IsNotOnOrAfter | not earlier than the expected value |
IsBefore | IsNotBefore | earlier than the expected value |
IsOnOrBefore | IsNotOnOrBefore | not later than the expected value |
IsBetween | IsNotBetween | between two values, both bounds included |
HasYear, … | negated comparison | has the expected year, month, day, hour, … |
HasKind | negated comparison | a DateTime with the expected Kind |
HasOffset | negated comparison | a DateTimeOffset with the expected Offset |
Equality
You can verify that the DateTime or DateTimeOffset is equal to another one or not:
- DateTime
- DateTimeOffset
DateTime releaseDate = new DateTime(1969, 9, 26);
await Expect.That(releaseDate).IsEqualTo(new DateTime(1969, 9, 26));
await Expect.That(releaseDate).IsNotEqualTo(new DateTime(1970, 5, 8));
DateTimeOffset releaseDate = new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1));
await Expect.That(releaseDate).IsEqualTo(new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1)));
await Expect.That(releaseDate).IsNotEqualTo(new DateTimeOffset(1970, 5, 8, 10, 0, 0, TimeSpan.FromHours(1)));
One of
You can verify that the DateTime or DateTimeOffset is one of many alternatives:
- DateTime
- DateTimeOffset
DateTime releaseDate = new DateTime(1969, 9, 26);
await Expect.That(releaseDate).IsOneOf([new DateTime(1969, 9, 26), new DateTime(1970, 5, 8)]);
await Expect.That(releaseDate).IsNotOneOf([new DateTime(1965, 8, 6), new DateTime(1966, 8, 5)]);
DateTimeOffset releaseDate = new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1));
await Expect.That(releaseDate).IsOneOf([
new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1)),
new DateTimeOffset(1970, 5, 8, 10, 0, 0, TimeSpan.FromHours(1))]);
await Expect.That(releaseDate).IsNotOneOf([
new DateTimeOffset(1965, 8, 6, 10, 0, 0, TimeSpan.FromHours(1)),
new DateTimeOffset(1966, 8, 5, 10, 0, 0, TimeSpan.FromHours(1))]);
After / before
You can verify that the DateTime or DateTimeOffset is (on or) after or before another value, or that it is not:
- DateTime
- DateTimeOffset
DateTime releaseDate = new DateTime(1969, 9, 26);
await Expect.That(releaseDate).IsAfter(new DateTime(1968, 11, 22));
await Expect.That(releaseDate).IsOnOrAfter(new DateTime(1969, 9, 26));
await Expect.That(releaseDate).IsBefore(new DateTime(1970, 5, 8));
await Expect.That(releaseDate).IsOnOrBefore(new DateTime(1969, 9, 26));
await Expect.That(releaseDate).IsNotAfter(new DateTime(1970, 5, 8));
DateTimeOffset releaseDate = new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1));
await Expect.That(releaseDate).IsAfter(new DateTimeOffset(1968, 11, 22, 10, 0, 0, TimeSpan.FromHours(1)));
await Expect.That(releaseDate).IsOnOrAfter(new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1)));
await Expect.That(releaseDate).IsBefore(new DateTimeOffset(1970, 5, 8, 10, 0, 0, TimeSpan.FromHours(1)));
await Expect.That(releaseDate).IsOnOrBefore(new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1)));
await Expect.That(releaseDate).IsNotAfter(new DateTimeOffset(1970, 5, 8, 10, 0, 0, TimeSpan.FromHours(1)));
Between
You can verify that the DateTime or DateTimeOffset is between two values, or that it is not:
- DateTime
- DateTimeOffset
DateTime releaseDate = new DateTime(1969, 9, 26);
await Expect.That(releaseDate).IsBetween(new DateTime(1969, 1, 1)).And(new DateTime(1969, 12, 31));
await Expect.That(releaseDate).IsNotBetween(new DateTime(1970, 1, 1)).And(new DateTime(1970, 12, 31));
DateTimeOffset releaseDate = new DateTimeOffset(1969, 9, 26, 10, 0, 0, TimeSpan.FromHours(1));
await Expect.That(releaseDate)
.IsBetween(new DateTimeOffset(1969, 1, 1, 0, 0, 0, TimeSpan.FromHours(1)))
.And(new DateTimeOffset(1969, 12, 31, 23, 59, 59, TimeSpan.FromHours(1)));
await Expect.That(releaseDate)
.IsNotBetween(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.FromHours(1)))
.And(new DateTimeOffset(1970, 12, 31, 23, 59, 59, TimeSpan.FromHours(1)));
Tolerance
Every comparison on this page except the Has… properties accepts a tolerance with Within, which widens the
accepted range by the tolerance, the same way for DateTime and DateTimeOffset:
DateTime importedAt = DateTime.Now;
await Expect.That(importedAt).IsEqualTo(DateTime.Now).Within(TimeSpan.FromSeconds(1))
.Because("the import should have taken less than one second");
await Expect.That(importedAt).IsOneOf([DateTime.Now]).Within(TimeSpan.FromSeconds(1));
await Expect.That(importedAt).IsAfter(DateTime.Now).Within(TimeSpan.FromSeconds(1));
await Expect.That(importedAt).IsOnOrBefore(DateTime.Now).Within(TimeSpan.FromSeconds(1));
await Expect.That(importedAt).IsBetween(DateTime.Today).And(DateTime.Now).Within(TimeSpan.FromSeconds(1));
Default tolerance
On Windows the DateTime resolution is about 10 to 15 milliseconds, so
comparing them as exact values might result in brittle tests. Therefore, it is possible to specify a default tolerance
that is used when a DateTime, DateTimeOffset, DateOnly, TimeOnly or TimeSpan subject is compared directly
(e.g. with IsEqualTo, IsOneOf, IsBefore or IsBetween) and no explicit tolerance is given:
using aweXpect.Chronology; // from the aweXpect.Chronology package
using aweXpect.Customization;
IDisposable lifetime = Customize.aweXpect.Settings().DefaultTimeComparisonTolerance.Set(15.Milliseconds());
It also applies to the items of a collection of DateTime, DateTimeOffset or TimeSpan values (or their nullable
counterparts) compared with IsEqualTo, IsNotEqualTo or All().AreEqualTo. An explicit Within always replaces the
default tolerance. The applied default tolerance is part of the failure message, for example
is equal to 2024-12-24T13:15:00.0000000 ± 0:00.015, unless it is zero.
For a DateOnly only the whole days of the default tolerance apply, so a default below one day has no effect there. An
explicit Within on a DateOnly still has to be a whole number of days.
The default tolerance is not used for:
- property verifications like
HasOffset() - other collection expectations, like
Contains - members compared by
IsEquivalentTo - values compared as
object
Kind
A DateTime with DateTimeKind.Utc and one with DateTimeKind.Local describe different instants even when their date
and time components are identical, so aweXpect refuses to compare them. A value with DateTimeKind.Unspecified is
compatible with both kinds. DateTimeOffset carries an explicit offset instead of a Kind and is therefore always
comparable.
IsEqualTo, IsOneOf, IsAfter, IsBefore, IsOnOrAfter, IsOnOrBefore and IsBetween fail for such a pair, and so
do the negated ordering expectations IsNotAfter, IsNotBefore, IsNotOnOrAfter, IsNotOnOrBefore and IsNotBetween.
Only IsNotEqualTo and IsNotOneOf succeed, because the two values are never equal:
DateTime releaseDate = new DateTime(1969, 9, 26, 0, 0, 0, DateTimeKind.Utc);
// fails with "but it had kind Utc, which cannot be compared with Local"
await Expect.That(releaseDate).IsBefore(new DateTime(1969, 9, 27, 0, 0, 0, DateTimeKind.Local));
await Expect.That(releaseDate).IsNotEqualTo(new DateTime(1969, 9, 26, 0, 0, 0, DateTimeKind.Local));
await Expect.That(releaseDate).IsEqualTo(new DateTime(1969, 9, 26, 0, 0, 0, DateTimeKind.Unspecified));
For IsBetween and IsNotBetween the subject must be comparable to both bounds. For IsOneOf and IsNotOneOf an
alternative with an incompatible Kind can never be the match, but the remaining alternatives are still considered.
The same rule applies wherever a DateTime is compared as a value: collection expectations such as IsEqualTo or
Contains, and IsEquivalentTo for a DateTime member. Two values that differ only in their kind never match
there either:
DateTime[] releaseDates = [new DateTime(1969, 9, 26, 0, 0, 0, DateTimeKind.Utc)];
// fails, because the expected value denotes a different instant
await Expect.That(releaseDates).Contains(new DateTime(1969, 9, 26, 0, 0, 0, DateTimeKind.Local));
Properties
You can verify the properties of DateTime or DateTimeOffset:
DateTime importedAt = new DateTime(2024, 12, 31, 15, 16, 17, 189, DateTimeKind.Utc);
// or: DateTimeOffset importedAt = new DateTimeOffset(2024, 12, 31, 15, 16, 17, 189, TimeSpan.FromMinutes(90));
await Expect.That(importedAt).HasYear(2024);
await Expect.That(importedAt).HasMonth(12);
await Expect.That(importedAt).HasDay(31);
await Expect.That(importedAt).HasHour().GreaterThan(12);
await Expect.That(importedAt).HasMinute(16);
await Expect.That(importedAt).HasSecond(17);
await Expect.That(importedAt).HasMillisecond().LessThan(500);
For DateTime you can also verify the Kind property, and for DateTimeOffset the Offset property:
- DateTime
- DateTimeOffset
DateTime importedAt = new DateTime(2024, 12, 31, 15, 16, 17, 189, DateTimeKind.Utc);
await Expect.That(importedAt).HasKind(DateTimeKind.Utc);
await Expect.That(importedAt).HasKind().NotEqualTo(DateTimeKind.Local);
DateTimeOffset importedAt = new DateTimeOffset(2024, 12, 31, 15, 16, 17, 189, TimeSpan.FromMinutes(90));
await Expect.That(importedAt).HasOffset(TimeSpan.FromMinutes(90));
await Expect.That(importedAt).HasOffset().GreaterThan(TimeSpan.Zero);
The Has… expectations for a number or a TimeSpan, e.g. HasLength(), HasCount(), HasYear() or HasMajor(),
continue with one of the following comparisons, each with a negated counterpart:
| Comparison | Negated | Succeeds when the value is |
|---|---|---|
EqualTo(x) | NotEqualTo(x) | equal to x |
GreaterThan(x) | NotGreaterThan(x) | greater than x |
GreaterThanOrEqualTo(x) | NotGreaterThanOrEqualTo(x) | greater than or equal to x |
LessThan(x) | NotLessThan(x) | less than x |
LessThanOrEqualTo(x) | NotLessThanOrEqualTo(x) | less than or equal to x |
Between(min).And(max) | NotBetween(min).And(max) | between min and max, both bounds included |
Passing the value directly, e.g. HasLength(10), is a shorthand for EqualTo.
The expected value is nullable, e.g. to pass a value mapped from a property. As the actual value is never null,
EqualTo(null) fails and NotEqualTo(null) succeeds, while a comparison of order against null, such as
GreaterThan(null) or Between(null).And(3), fails even when negated.
HasKind() only supports EqualTo and NotEqualTo.