-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
280 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -348,3 +348,5 @@ MigrationBackup/ | |
|
||
# Ionide (cross platform F# VS Code tools) working folder | ||
.ionide/ | ||
|
||
.vscode/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using Unosquare.DateTimeExt.Interfaces; | ||
|
||
namespace Unosquare.DateTimeExt; | ||
|
||
public abstract class YearWeekBase(DateTime startDate, DateTime endDate) | ||
: DateRange(startDate, endDate), IYearWeekDateRange | ||
{ | ||
protected const int WeekDays = 7; | ||
|
||
public abstract int Year { get; } | ||
public abstract int Week { get; } | ||
|
||
public YearEntity BoWYearEntity => new(StartDate.Year); | ||
public YearEntity EoWYearEntity => new(EndDate.Year); | ||
|
||
public new YearWeekRecord ToRecord() => new() { Year = Year, Week = Week }; | ||
|
||
public void Deconstruct(out int year, out int week) | ||
{ | ||
year = Year; | ||
week = Week; | ||
} | ||
|
||
public override string ToString() => $"{Year}-W{Week}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using Unosquare.DateTimeExt.Interfaces; | ||
|
||
namespace Unosquare.DateTimeExt; | ||
|
||
public sealed class YearWeekIso : YearWeekBase, IComparable<YearWeekIso> | ||
{ | ||
public YearWeekIso(int week, int year) | ||
: base(ISOWeek.ToDateTime(year, week, DayOfWeek.Monday), ISOWeek.ToDateTime(year, week, DayOfWeek.Sunday)) | ||
{ | ||
} | ||
|
||
public YearWeekIso(IYearWeek yearWeek) | ||
: this(yearWeek.Week, yearWeek.Year) | ||
{ | ||
} | ||
|
||
public YearWeekIso(IHasReadOnlyWeek readOnlyWeek, IHasReadOnlyYear readOnlyYear) | ||
: this(readOnlyWeek.Week, readOnlyYear.Year) | ||
{ | ||
} | ||
|
||
public YearWeekIso(DateTime? dateTime = null) | ||
: this(ISOWeek.GetWeekOfYear(dateTime ?? DateTime.UtcNow), ISOWeek.GetYear(dateTime ?? DateTime.UtcNow)) | ||
{ | ||
} | ||
|
||
public static YearWeekIso Current => new(); | ||
|
||
public override int Week => ISOWeek.GetWeekOfYear(StartDate); | ||
public override int Year => ISOWeek.GetYear(StartDate); | ||
|
||
public YearWeekIso Next => new(StartDate.AddDays(WeekDays)); | ||
|
||
public YearWeekIso Previous => new(StartDate.AddDays(-WeekDays)); | ||
|
||
public bool IsCurrent => IsCurrentYear && Week == ISOWeek.GetWeekOfYear(DateTime.UtcNow); | ||
|
||
public bool IsCurrentYear => Year == ISOWeek.GetYear(DateTime.UtcNow); | ||
|
||
public YearWeekIso AddWeeks(int count) => new(StartDate.AddDays(WeekDays * count)); | ||
|
||
public YearWeekIso ToWeek(int week) => new(week, Year); | ||
|
||
public int CompareTo(YearWeekIso? other) | ||
{ | ||
if (ReferenceEquals(this, other)) | ||
return 0; | ||
|
||
return other is null ? 1 : base.CompareTo(other); | ||
} | ||
|
||
public static bool TryParse(string? value, out YearWeekIso result) | ||
{ | ||
result = default!; | ||
|
||
if (string.IsNullOrWhiteSpace(value)) | ||
return false; | ||
|
||
var parts = value.Split('-', 'W'); | ||
Check warning on line 59 in src/Unosquare.DateTimeExt/YearWeekIso.cs GitHub Actions / Build
|
||
|
||
if (parts.Length != 3 || !int.TryParse(parts[0], out var year) || !int.TryParse(parts[2], out var week)) | ||
{ | ||
return false; | ||
} | ||
|
||
result = new(week, year); | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
176 changes: 176 additions & 0 deletions
176
test/Unosquare.DateTimeExt.Test/Unosquare.DateTimeExt.Test/YearWeekIsoTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
namespace Unosquare.DateTimeExt.Test; | ||
|
||
public class YearWeekIsoTests | ||
{ | ||
[Fact] | ||
public void WithWeek_Deconstruct() | ||
{ | ||
var yearMonth = new YearWeekIso(1, 2022); | ||
yearMonth.Deconstruct(out DateTime startDate, out var endDate); | ||
|
||
Assert.Equal(new(2022, 1, 3), startDate); | ||
Assert.Equal(new(2022, 1, 9), endDate); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_FromDateTime() | ||
{ | ||
var yearMonth = new YearWeekIso(new DateTime(2022, 1, 2)); | ||
|
||
Assert.Equal(52, yearMonth.Week); | ||
Assert.Equal(2021, yearMonth.Year); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_DateRange() | ||
{ | ||
var yearMonth = new YearWeekIso(1, 2022); | ||
|
||
Assert.Equal(new(2022, 1, 3), yearMonth.StartDate); | ||
Assert.Equal(new(2022, 1, 9), yearMonth.EndDate); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_AddWeeksNegative() | ||
{ | ||
var yearMonth = new YearWeekIso(2, 2022); | ||
|
||
Assert.Equal(new(2022, 1, 3), yearMonth.AddWeeks(-1).StartDate); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_AddWeeksPositive() | ||
{ | ||
var yearMonth = new YearWeekIso(1, 2022); | ||
|
||
Assert.Equal(new(2022, 1, 10), yearMonth.AddWeeks(1).StartDate); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_Previous() | ||
{ | ||
var yearMonth = new YearWeekIso(2, 2022); | ||
|
||
Assert.Equal(new(2022, 1, 3), yearMonth.Previous.StartDate); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_Next() | ||
{ | ||
var yearMonth = new YearWeekIso(1, 2022); | ||
|
||
Assert.Equal(new(2022, 1, 10), yearMonth.Next.StartDate); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_IsCurrent() | ||
{ | ||
var yearMonth = new YearWeekIso(); | ||
|
||
Assert.True(yearMonth.IsCurrent); | ||
} | ||
|
||
[Fact] | ||
public void WithWeek_DeconstructYearMonth() | ||
{ | ||
var yearMonth = new YearWeekIso(1, 2022); | ||
yearMonth.Deconstruct(out int year, out int week); | ||
|
||
Assert.Equal(1, week); | ||
Assert.Equal(2022, year); | ||
} | ||
|
||
[Fact] | ||
public void TryParse_Valid_WeekYearString_ReturnsTrue() | ||
{ | ||
// Arrange | ||
const string input = "2022-W01"; | ||
YearWeekIso expected = new(1, 2022); | ||
|
||
// Act | ||
bool result = YearWeekIso.TryParse(input, out var actual); | ||
|
||
// Assert | ||
Assert.True(result); | ||
Assert.Equal(expected, actual); | ||
} | ||
|
||
[Fact] | ||
public void TryParse_Invalid_WeekYearString_ReturnsFalse() | ||
{ | ||
// Arrange | ||
const string input = "not a valid input string"; | ||
|
||
// Act | ||
bool result = YearWeekIso.TryParse(input, out var actual); | ||
|
||
// Assert | ||
Assert.False(result); | ||
Assert.Null(actual); | ||
} | ||
|
||
[Fact] | ||
public void YearWeekIso_Current() | ||
{ | ||
var yearWeek = YearWeekIso.Current; | ||
|
||
Assert.Equal(DateTime.UtcNow.Month == 1 && DateTime.UtcNow.GetWeekOfYear() > 5 | ||
? DateTime.UtcNow.Year - 1 | ||
: DateTime.UtcNow.Year, yearWeek.Year); | ||
} | ||
|
||
[Fact] | ||
public void YearWeekIso_BoWYearEntity() | ||
{ | ||
var yearWeek = new YearWeekIso(1, 2022); | ||
var yearWeekBoW = yearWeek.BoWYearEntity; | ||
|
||
Assert.Equal(yearWeek.Year, yearWeekBoW.Year); | ||
Assert.Equal(yearWeek.StartDate.Month, yearWeekBoW.StartDate.Month); | ||
Assert.Equal(1, yearWeekBoW.StartDate.Day); | ||
} | ||
|
||
[Fact] | ||
public void YearWeekIso_EoWYearEntity() | ||
{ | ||
var yearWeek = new YearWeekIso(1, 2022); | ||
var yearWeekBoW = yearWeek.EoWYearEntity; | ||
|
||
Assert.Equal(yearWeek.Year, yearWeekBoW.Year); | ||
Assert.Equal(yearWeek.StartDate.Month, yearWeekBoW.StartDate.Month); | ||
Assert.Equal(1, yearWeekBoW.StartDate.Day); | ||
} | ||
|
||
[Fact] | ||
public void YearWeekIso_ToRecord() | ||
{ | ||
var yearWeek = new YearWeekIso(1, 2022); | ||
var record = yearWeek.ToRecord(); | ||
|
||
Assert.Equal(yearWeek.Year, record.Year); | ||
Assert.Equal(yearWeek.StartDate.Month, record.Week); | ||
} | ||
|
||
[Fact] | ||
public void YearWeekIso_Equals() | ||
{ | ||
var yearWeek1 = new YearWeekIso(1, 2022); | ||
var yearWeek2 = new YearWeekIso(1, 2022); | ||
var yearWeek3 = new YearWeekIso(2, 2022); | ||
|
||
Assert.True(yearWeek1.Equals(yearWeek2)); | ||
Assert.False(yearWeek1.Equals(yearWeek3)); | ||
} | ||
|
||
[Fact] | ||
public void YearWeekIso_CompareTo() | ||
{ | ||
var yearWeek1 = new YearWeekIso(1, 2022); | ||
var yearWeek2 = new YearWeekIso(1, 2022); | ||
var yearWeek3 = new YearWeekIso(2, 2022); | ||
|
||
Assert.Equal(0, yearWeek1.CompareTo(yearWeek2)); | ||
Assert.Equal(-1, yearWeek1.CompareTo(yearWeek3)); | ||
Assert.Equal(1, yearWeek3.CompareTo(yearWeek1)); | ||
} | ||
} |