Skip to content

Commit

Permalink
DateTimeOfffset as return type for Clock.Now(). (#377)
Browse files Browse the repository at this point in the history
  • Loading branch information
Corniel committed Feb 23, 2024
1 parent 59f982e commit 1cfaf58
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 20 deletions.
10 changes: 5 additions & 5 deletions specs/Qowaiv.Specs/Clock_specs.cs
Expand Up @@ -17,17 +17,17 @@ public void Now_equals_UTC_now_with_the_time_zone_offset()
{
using (Clock.SetTimeAndTimeZoneForCurrentContext(() => Svo.DateTime, TestTimeZones.EastAustraliaStandardTime))
{
Clock.Now().Should().Be(new LocalDateTime(2017, 06, 11, 16, 15, 00));
Clock.Now().Should().Be(new DateTimeOffset(2017, 06, 11, 16, 15, 00, TimeSpan.FromHours(+10)));
}
}

[Test]
public void NowWithOffset_equals_UTC_now_with_the_time_zone_offset()
public void Now_for_time_zone_equals_UTC_now_with_the_time_zone_offset()
{
using (Clock.SetTimeAndTimeZoneForCurrentContext(() => Svo.DateTime, Svo.TimeZone))
using (Clock.SetTimeAndTimeZoneForCurrentContext(() => Svo.DateTime, TestTimeZones.EastAustraliaStandardTime))
{
var date_time_offset = new DateTimeOffset(new DateTime(2017, 06, 11, 16, 15, 0, DateTimeKind.Unspecified), TimeSpan.FromHours(+10));
Clock.NowWithOffset().Should().Be(date_time_offset);
var now = Clock.Now(TestTimeZones.LeidenTime);
now.Should().Be(new DateTimeOffset(2017, 06, 11, 06, 48, 00, TimeSpan.FromMinutes(+33)));
}
}
}
Expand Down
78 changes: 78 additions & 0 deletions specs/Qowaiv.Specs/Date_time_offset_specs.cs
@@ -0,0 +1,78 @@
using FluentAssertions.Extensions;

namespace Date_time_offset_specs;

public class Can_be_adjusted_with
{
[Test]
public void Date_span_with_months_first()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).Add(new DateSpan(2, 20))
.Should().Be(31.August(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)));

[Test]
public void Date_span_with_days_first()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).Add(new DateSpan(2, 20), DateSpanSettings.DaysFirst)
.Should().Be(01.September(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)));

[Test]
public void Month_span()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).Add(MonthSpan.FromMonths(3))
.Should().Be(11.September(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)));
}

public class With_local
{
[Test]
public void represents_a_local_date_time()
{
11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).ToLocal()
.Should().Be(new LocalDateTime(2017, 06, 11, 06, 15));
}
}

public class Can_not_be_adjusted_with
{
[TestCase(DateSpanSettings.WithoutMonths)]
[TestCase(DateSpanSettings.DaysFirst | DateSpanSettings.MixedSigns)]
public void Date_span_with(DateSpanSettings settings)
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).Invoking(d => d.Add(new DateSpan(2, 20), settings))
.Should().Throw<ArgumentOutOfRangeException>().WithMessage("Adding a date span only supports 'Default' and 'DaysFirst'.*");
}

public class Can_be_related_to
{
[Test]
public void matching_month()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(Month.June).Should().BeTrue();

[Test]
public void none_matching_month()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(Month.February).Should().BeFalse();

[Test]
public void matching_year()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(2017.CE()).Should().BeTrue();

[Test]
public void none_matching_year()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(2018.CE()).Should().BeFalse();
}

public class Can_not_be_related_to
{
[Test]
public void month_empty()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(Month.Empty).Should().BeFalse();

[Test]
public void month_unknown()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(Month.Unknown).Should().BeFalse();

[Test]
public void year_empty()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(Year.Empty).Should().BeFalse();

[Test]
public void year_unknown()
=> 11.June(2017).At(06, 15).WithOffset(TimeSpan.FromHours(+2)).IsIn(Year.Unknown).Should().BeFalse();
}
17 changes: 3 additions & 14 deletions src/Qowaiv/Clock.cs
Expand Up @@ -17,7 +17,7 @@ namespace Qowaiv;
/// [Test]
/// public void TestSomething()
/// {
/// using(Clock.SetTimeForCurrentContext(() => new DateTime(2017, 06, 11, 00, 00, 000, DateTimeKind.Local))
/// using(Clock.SetTimeForCurrentContext(() => new DateTimeOffset(2017, 06, 11, 00, 00, 000, TimeSpan.FromHours(+1))
/// {
/// // test code.
/// }
Expand Down Expand Up @@ -47,27 +47,16 @@ public static DateTime UtcNow()
/// <summary>Gets the time zone of the <see cref="Clock"/>.</summary>
public static TimeZoneInfo TimeZone => localContextTimeZone.Value ?? globalTimeZone;

/// <summary>Gets the current <see cref="LocalDateTime"/>.</summary>
[Pure]
public static LocalDateTime Now() => Now(TimeZone);

/// <summary>Gets the current <see cref="LocalDateTime"/> for the specified time zone.</summary>
/// <param name="timeZone">
/// The specified time zone.
/// </param>
[Pure]
public static LocalDateTime Now(TimeZoneInfo timeZone) => TimeZoneInfo.ConvertTimeFromUtc(UtcNow(), Guard.NotNull(timeZone));

/// <summary>Gets the current <see cref="DateTimeOffset"/>.</summary>
[Pure]
public static DateTimeOffset NowWithOffset() => NowWithOffset(TimeZone);
public static DateTimeOffset Now() => Now(TimeZone);

/// <summary>Gets the current <see cref="DateTimeOffset"/> for the specified time zone.</summary>
/// <param name="timeZone">
/// The specified time zone.
/// </param>
[Pure]
public static DateTimeOffset NowWithOffset(TimeZoneInfo timeZone)
public static DateTimeOffset Now(TimeZoneInfo timeZone)
{
Guard.NotNull(timeZone);
var utcNow = UtcNow();
Expand Down
2 changes: 1 addition & 1 deletion src/Qowaiv/Extensions/System.DateTime.cs
Expand Up @@ -78,7 +78,7 @@ public static class QowaivDateTimeExtensions

/// <summary>Returns true if the date is in the specified month, otherwise false.</summary>
/// <param name="d">
/// The date to check.
/// The date time to check.
/// </param>
/// <param name="month">
/// The <see cref="Month"/> the date should be in.
Expand Down
106 changes: 106 additions & 0 deletions src/Qowaiv/Extensions/System.DateTimeOffset.cs
@@ -0,0 +1,106 @@
using Qowaiv;

namespace System;

/// <summary>Extensions on <see cref="DateTimeOffset"/>.</summary>
public static class QowaivDateTimeOffsetExtensions
{
/// <summary>Returns a new date time offset that adds the value of the specified <see cref="DateSpan"/>
/// to the value of this instance.
/// </summary>
/// <param name="d">
/// The date time offset to add a <see cref="DateSpan"/> to.
/// </param>
/// <param name="value">
/// A <see cref="DateSpan"/> object that represents a positive or negative time interval.
/// </param>
/// <returns>
/// A new date whose value is the sum of the date and time represented
/// by this instance and the time interval represented by value.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The resulting date is less than <see cref="DateTimeOffset.MinValue"/> or greater
/// than <see cref="DateTime.MaxValue"/>.
/// </exception>
[Pure]
public static DateTimeOffset Add(this DateTimeOffset d, DateSpan value) => d.Add(value, DateSpanSettings.Default);

/// <summary>Returns a new date time that adds the value of the specified <see cref="DateSpan"/>
/// to the value of this instance.
/// </summary>
/// <param name="d">
/// The date time to offset add a <see cref="MonthSpan"/> to.
/// </param>
/// <param name="value">
/// A <see cref="DateSpan"/> object that represents a positive or negative time interval.
/// </param>
/// <param name="settings">
/// If <see cref="DateSpanSettings.DaysFirst"/> days are added first, if <see cref="DateSpanSettings.Default"/> days are added second.
/// </param>
/// <returns>
/// A new date whose value is the sum of the date represented
/// by this instance and the time interval represented by value.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The resulting date is less than <see cref="DateTimeOffset.MinValue"/> or greater
/// than <see cref="DateTimeOffset.MaxValue"/>.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// The provided settings have different value then <see cref="DateSpanSettings.DaysFirst"/> or <see cref="DateSpanSettings.Default"/>.
/// </exception>
[Pure]
public static DateTimeOffset Add(this DateTimeOffset d, DateSpan value, DateSpanSettings settings) => settings switch
{
DateSpanSettings.DaysFirst => d.AddDays(value.Days).AddMonths(value.TotalMonths),
DateSpanSettings.Default => d.AddMonths(value.TotalMonths).AddDays(value.Days),
_ => throw new ArgumentOutOfRangeException(nameof(settings), QowaivMessages.ArgumentOutOfRangeException_AddDateSpan),
};

/// <summary>Returns a new date time that adds the value of the specified <see cref="MonthSpan"/>
/// to the value of this instance.
/// </summary>
/// <param name="d">
/// The date time offset to add a <see cref="MonthSpan"/> to.
/// </param>
/// <param name="value">
/// A <see cref="MonthSpan"/> object that represents a positive or negative time interval.
/// </param>
/// <returns>
/// A new date whose value is the sum of the date and time represented
/// by this instance and the time interval represented by value.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// The resulting date is less than <see cref="DateTimeOffset.MinValue"/> or greater
/// than <see cref="DateTimeOffset.MaxValue"/>.
/// </exception>
[Pure]
public static DateTimeOffset Add(this DateTimeOffset d, MonthSpan value) => d.AddMonths(value.TotalMonths);

/// <summary>Returns true if the date is in the specified month, otherwise false.</summary>
/// <param name="d">
/// The date time offset to check.
/// </param>
/// <param name="month">
/// The <see cref="Month"/> the date should be in.
/// </param>
[Pure]
public static bool IsIn(this DateTimeOffset d, Month month) => !month.IsEmptyOrUnknown() && d.Month == (int)month;

/// <summary>Returns true if the date is in the specified year, otherwise false.</summary>
/// <param name="d">
/// The date time offset to check.
/// </param>
/// <param name="year">
/// The <see cref="Year"/> the date should be in.
/// </param>
[Pure]
public static bool IsIn(this DateTimeOffset d, Year year) => !year.IsEmptyOrUnknown() && d.Year == (int)year;

/// <summary>Returns the <see cref="LocalDateTime"/> representation of the date time offset.</summary>
/// <param name="d">
/// The date time offset.
/// </param>
[Pure]
public static LocalDateTime ToLocal(this DateTimeOffset d)
=> new(d.LocalDateTime.Ticks);
}
3 changes: 3 additions & 0 deletions src/Qowaiv/Qowaiv.csproj
Expand Up @@ -9,6 +9,9 @@
<PackageId>Qowaiv</PackageId>
<PackageReleaseNotes>
v7.0.0
- Clock.Now returns DateTimeOffset. (breaking)
- Clock.NowWithOffset is dropped. (breaking)
- Extension methods on DateTimeOffset.
- Implement INumber&lt;Percentage&gt;. #367
- Implement INumber&lt;Amount&gt;. #370
- Introduction of the IEmpty&lt;TSelf&gt; interface. #364
Expand Down

0 comments on commit 1cfaf58

Please sign in to comment.