Skip to content

Commit 9cc748e

Browse files
committed
# Conflicts: # tests/MoreDateTime.Test/Extensions/DateOnlyExtensionsTests.cs
2 parents a01a79c + e83fc8d commit 9cc748e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+3198
-117
lines changed

.github/dependabot.yml

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ updates:
88
schedule:
99
interval: "daily"
1010
reviewers:
11-
- "tinohager"
12-
- "samtrion"
11+
- "hefaistos68"
1312
commit-message:
1413
prefix: chore
1514
prefix-development: chore(dev)

.github/workflows/dotnet.yml

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: Build, Test & Publish
22

33
on:
4+
workflow_dispatch:
45
push:
56
paths:
67
- 'src/**'
@@ -45,3 +46,8 @@ jobs:
4546
run: |
4647
cd $GITHUB_WORKSPACE/out
4748
dotnet nuget push *.nupkg --source https://www.nuget.org/api/v2/package --api-key ${{secrets.NUGET_TOKEN}} --skip-duplicate --no-symbols
49+
- name: Push Github package
50+
if: github.event_name != 'pull_request'
51+
run: |
52+
cd $GITHUB_WORKSPACE/out
53+
dotnet nuget add source --username Hefaistos68 --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/Hefaistos68/index.json"

.github/workflows/manual.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# This is a basic workflow that is manually triggered
2+
3+
name: Manual workflow
4+
5+
# Controls when the action will run. Workflow runs when manually triggered using the UI
6+
# or API.
7+
on:
8+
workflow_dispatch:
9+
jobs:
10+
build:
11+
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v3
16+
- name: Setup .NET 6.0
17+
uses: actions/setup-dotnet@v3
18+
with:
19+
dotnet-version: 6.0.x
20+
- name: Change LicenseKey
21+
working-directory: ./tests
22+
run: |
23+
sed -i 's/Thank you for supporting open source projects/${{secrets.LICENSE_KEY}}/g' MoreDateTime.Test/AssemblyInitialize.cs
24+
- name: Restore dependencies
25+
working-directory: .
26+
run: dotnet restore
27+
- name: Build
28+
working-directory: .
29+
run: dotnet build --configuration Release --no-restore
30+
- name: Test
31+
working-directory: .
32+
run: |
33+
dotnet test --configuration Release --no-restore --no-build --verbosity normal

CONTRIBUTING.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
All contributions are welcome, as long as they are in the scope of the project: extending the use of and functionality of the Date and Time related objects in .NET (namely DateTime, DateOnly, TimeOnly and TimeSpan)
2+
3+
Please adhere to the general C# .NET rules and guidelines, use comments and names that make common sense.
4+
If you are not sure if you should add something to the library, or have an idea and dont know how and where to start, just get in touch and we discuss it.
5+
6+
Submit your PRs and I get back to them asap.

build/.build.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<OldToolsVersion>2.0</OldToolsVersion>
1111
</PropertyGroup>
1212
<ItemGroup>
13-
<PackageReference Include="Nuke.Common" Version="0.22.2" />
13+
<PackageReference Include="Nuke.Common" Version="6.3.0" />
1414
<PackageReference Include="GitVersion.CommandLine" Version="5.12.0" />
1515
</ItemGroup>
1616
</Project>

src/MoreDateTime/DateOnlyRange.cs

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using MoreDateTime.Extensions;
2+
using MoreDateTime.Interfaces;
3+
4+
namespace MoreDateTime
5+
{
6+
/// <summary>
7+
/// Implements the <see cref="IDateOnlyRange"/> interface and provides a time range through its <see cref="Start"/> and <see cref="End"/> members
8+
/// </summary>
9+
public class DateOnlyRange : IDateOnlyRange
10+
{
11+
/// <summary>
12+
/// Initializes a new instance of the <see cref="DateOnlyRange"/> class.
13+
/// </summary>
14+
/// <param name="startTime">The start DateOnly</param>
15+
/// <param name="endTime">The end DateOnly</param>
16+
public DateOnlyRange(DateOnly startTime, DateOnly endTime)
17+
{
18+
Start = startTime;
19+
End = endTime;
20+
}
21+
22+
/// <inheritdoc/>
23+
public TimeSpan Distance()
24+
{
25+
return this.Start.Distance(this.End);
26+
}
27+
28+
/// <inheritdoc/>
29+
public DateOnly Start { get; set; }
30+
31+
/// <inheritdoc/>
32+
public DateOnly End { get; set; }
33+
}
34+
35+
}

src/MoreDateTime/DateTimeRange.cs

+23-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using System;
22

3+
using MoreDateTime.Extensions;
34
using MoreDateTime.Interfaces;
45

56
namespace MoreDateTime
67
{
78
/// <summary>
8-
/// Implements the <see cref="IDateTimeRange"/> interface and provides a time range through its <see cref="StartTime"/> and <see cref="EndTime"/> members
9+
/// Implements the <see cref="IDateTimeRange"/> interface and provides a time range through its <see cref="Start"/> and <see cref="End"/> members
910
/// </summary>
1011
public class DateTimeRange : IDateTimeRange
1112
{
@@ -16,15 +17,31 @@ public class DateTimeRange : IDateTimeRange
1617
/// <param name="endTime">The end datetime</param>
1718
public DateTimeRange(DateTime startTime, DateTime endTime)
1819
{
19-
StartTime = startTime;
20-
EndTime = endTime;
20+
Start = startTime;
21+
End = endTime;
22+
}
23+
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="DateTimeRange"/> class.
26+
/// </summary>
27+
/// <param name="startTime">The start datetime</param>
28+
/// <param name="endTime">The end datetime</param>
29+
public DateTimeRange(DateOnly startTime, DateOnly endTime)
30+
{
31+
Start = startTime.ToDateTime();
32+
End = endTime.ToDateTime(); // Should we include this day until midnight - 1 millisecond?
33+
}
34+
35+
/// <inheritdoc/>
36+
public TimeSpan Distance()
37+
{
38+
return this.Start.Distance(this.End);
2139
}
2240

2341
/// <inheritdoc/>
24-
public DateTime StartTime { get; set; }
42+
public DateTime Start { get; set; }
2543

2644
/// <inheritdoc/>
27-
public DateTime EndTime { get; set; }
45+
public DateTime End { get; set; }
2846
}
29-
3047
}

src/MoreDateTime/Extensions/DateOnlyExtensions.Enumerate.cs

+24-2
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,22 @@ public static IEnumerable<DateOnly> EnumerateInStepsUntil(this DateOnly startDat
3434

3535
if (startDate < endDate)
3636
{
37+
if (distance.Ticks < 0)
38+
{
39+
throw new ArgumentOutOfRangeException(nameof(distance), "Distance must be positive when going forwards");
40+
}
41+
3742
endDate2 = endDate2.Add(_enumerationGap);
3843
for (var step = startDate2.Date; step < endDate2; step = step.Add(distance))
3944
yield return step.ToDateOnly();
4045
}
4146
else
4247
{
48+
if (distance.Ticks > 0)
49+
{
50+
throw new ArgumentOutOfRangeException(nameof(distance), "Distance must be negative when going backwards");
51+
}
52+
4353
endDate2 = endDate2.Sub(_enumerationGap);
4454
for (var step = startDate2.Date; step >= endDate2; step = step.Add(distance))
4555
yield return step.ToDateOnly();
@@ -71,6 +81,12 @@ public static IEnumerable<DateOnly> EnumerateInStepsUntil(this DateOnly startDat
7181

7282
if (startDate < endDate)
7383
{
84+
// make sure distance is negative if we are going forwards
85+
if (distance.Ticks < 0)
86+
{
87+
throw new ArgumentOutOfRangeException(nameof(distance), "Distance must be positive when going forwards");
88+
}
89+
7490
for (var step = startDate2.Date; step.Date <= endDate2.Date; step = step.Add(distance))
7591
{
7692
var dateOnly = step.ToDateOnly();
@@ -80,6 +96,12 @@ public static IEnumerable<DateOnly> EnumerateInStepsUntil(this DateOnly startDat
8096
}
8197
else
8298
{
99+
// make sure distance is negative if we are going backwards
100+
if (distance.Ticks > 0)
101+
{
102+
throw new ArgumentOutOfRangeException(nameof(distance), "Distance must be negative when going backwards");
103+
}
104+
83105
for (var step = startDate2.Date; step.Date >= endDate2.Date; step = step.Add(distance))
84106
{
85107
var dateOnly = step.ToDateOnly();
@@ -100,7 +122,7 @@ public static IEnumerable<DateOnly> EnumerateDaysUntil(this DateOnly from, DateO
100122
{
101123
if (to <= from)
102124
{
103-
for (var day = from; day >= to; day = day.NextDay())
125+
for (var day = from; day >= to; day = day.PreviousDay())
104126
yield return day;
105127
}
106128
else
@@ -132,7 +154,7 @@ public static IEnumerable<DateOnly> EnumerateWorkdaysUntil(this DateOnly from, D
132154
}
133155

134156
/// <summary>
135-
/// Advances to the closest weekend and enumerates the weekends until the end date
157+
/// Advances to the closest weekend and enumerates the weekends until the end date. The weekend date is always a saturday when going forward and a sunday when going backwards.
136158
/// </summary>
137159
/// <param name="from">The starting DateOnly value</param>
138160
/// <param name="to">The ending DateOnly value</param>

src/MoreDateTime/Extensions/DateOnlyExtensions.Is.cs

+35-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace MoreDateTime.Extensions
1313
public static partial class DateOnlyExtensions
1414
{
1515
/// <summary>
16-
/// Checks if the given value is between the given startDate and endDate values
16+
/// Checks if the given value is between the given startDate and endDate values, excluding the start and end value
1717
/// </summary>
1818
/// <param name="me">The DateOnly to compare</param>
1919
/// <param name="startDate">The startDate date</param>
@@ -26,6 +26,40 @@ public static bool IsBetween(this DateOnly me, DateOnly startDate, DateOnly endD
2626
throw new ArgumentException("End must be greater than startDate");
2727
}
2828

29+
return (me > startDate) && (me < endDate);
30+
}
31+
32+
/// <summary>
33+
/// Checks if the given value is within the given startDate and endDate values, including startDate and endDate
34+
/// </summary>
35+
/// <param name="me">The DateTime to compare</param>
36+
/// <param name="startDate">The startDate date</param>
37+
/// <param name="endDate">The endDate date</param>
38+
/// <returns>True if the value is greater or equal startDate and less than or equal endDate</returns>
39+
public static bool IsWithin(this DateOnly me, DateTime startDate, DateTime endDate)
40+
{
41+
if (endDate < startDate)
42+
{
43+
throw new ArgumentException("End must be greater than startDate");
44+
}
45+
46+
return (me >= startDate.ToDateOnly()) && (me <= endDate.ToDateOnly());
47+
}
48+
49+
/// <summary>
50+
/// Checks if the given value is within the given startDate and endDate values, including startDate and endDate
51+
/// </summary>
52+
/// <param name="me">The DateTime to compare</param>
53+
/// <param name="startDate">The startDate date</param>
54+
/// <param name="endDate">The endDate date</param>
55+
/// <returns>True if the value is greater or equal startDate and less than or equal endDate</returns>
56+
public static bool IsWithin(this DateOnly me, DateOnly startDate, DateOnly endDate)
57+
{
58+
if (endDate < startDate)
59+
{
60+
throw new ArgumentException("End must be greater than startDate");
61+
}
62+
2963
return (me >= startDate) && (me <= endDate);
3064
}
3165

src/MoreDateTime/Extensions/DateOnlyExtensions.IsSame.cs

+54
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,59 @@ public static bool IsSameYear(this DateOnly dt, DateOnly other)
6666
{
6767
return dt.Year == other.Year;
6868
}
69+
/// <summary>
70+
/// Verifies if the two dates are the same day of the month
71+
/// </summary>
72+
/// <param name="dt">The first DateOnly argument</param>
73+
/// <param name="other">The DateOnly argument to compare with</param>
74+
/// <returns>True if the dates are on the same day</returns>
75+
public static bool IsSameDay(this DateOnly dt, DateTime other)
76+
{
77+
return dt.Day == other.Day;
78+
}
79+
80+
/// <summary>
81+
/// Verifies if the two dates are the same month
82+
/// </summary>
83+
/// <param name="dt">The first DateOnly argument</param>
84+
/// <param name="other">The DateOnly argument to compare with</param>
85+
/// <returns>True if the dates are on the same month</returns>
86+
public static bool IsSameMonth(this DateOnly dt, DateTime other)
87+
{
88+
return dt.Month == other.Month;
89+
}
90+
91+
/// <summary>
92+
/// Verifies if the two dates are the same week
93+
/// </summary>
94+
/// <param name="dt">The first DateOnly argument</param>
95+
/// <param name="other">The DateOnly argument to compare with</param>
96+
/// <returns>True if the dates are on the same week</returns>
97+
public static bool IsSameWeek(this DateOnly dt, DateTime other, CultureInfo? cultureInfo = null)
98+
{
99+
return dt.WeekOfYear(cultureInfo) == other.WeekOfYear(cultureInfo);
100+
}
101+
102+
/// <summary>
103+
/// Verifies if the two dates are the same weekday
104+
/// </summary>
105+
/// <param name="dt">The first DateOnly argument</param>
106+
/// <param name="other">The DateOnly argument to compare with</param>
107+
/// <returns>True if the dates are on the same weekday</returns>
108+
public static bool IsSameWeekday(this DateOnly dt, DateTime other)
109+
{
110+
return dt.DayOfWeek == other.DayOfWeek;
111+
}
112+
113+
/// <summary>
114+
/// Verifies if the two dates are the same year
115+
/// </summary>
116+
/// <param name="dt">The first <see cref="DateOnly"/> argument</param>
117+
/// <param name="other">The DateOnly argument to compare with</param>
118+
/// <returns>True if the dates are on the same year</returns>
119+
public static bool IsSameYear(this DateOnly dt, DateTime other)
120+
{
121+
return dt.Year == other.Year;
122+
}
69123
}
70124
}

src/MoreDateTime/Extensions/DateOnlyExtensions.NextPrev.cs

+25-4
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,24 @@ public static DateOnly NextWeek(this DateOnly dt)
5959
}
6060

6161
/// <summary>
62-
/// Gets the DateOnly value of the next weekend following this date
62+
/// Gets the DateOnly value of the next weekend following this date. If the given date is already a weekend, the next weekend is returned.
6363
/// </summary>
6464
/// <param name="dt">The DateOnly object</param>
6565
/// <returns>A DateOnly object</returns>
6666
public static DateOnly NextWeekend(this DateOnly dt)
6767
{
68-
throw new NotImplementedException();
68+
// if its already a weekend, skip it
69+
while (dt.IsWeekend())
70+
{
71+
dt = dt.NextDay();
72+
}
73+
74+
while (!dt.IsWeekend())
75+
{
76+
dt = dt.NextDay();
77+
}
78+
79+
return dt;
6980
}
7081

7182
/// <summary>
@@ -170,13 +181,23 @@ public static DateOnly PreviousWeek(this DateOnly dt)
170181
}
171182

172183
/// <summary>
173-
/// Gets the DateOnly value of the weekend before this date
184+
/// Gets the DateOnly value of the weekend before this date. If the given date is already a weekend, the previous weekend is returned.
174185
/// </summary>
175186
/// <param name="dt">The DateOnly object</param>
176187
/// <returns>A DateOnly object whose value is the week before the given, the weekday and time is not changed</returns>
177188
public static DateOnly PreviousWeekend(this DateOnly dt)
178189
{
179-
throw new NotImplementedException();
190+
while (dt.IsWeekend())
191+
{
192+
dt = dt.PreviousDay();
193+
}
194+
195+
while (!dt.IsWeekend())
196+
{
197+
dt = dt.PreviousDay();
198+
}
199+
200+
return dt;
180201
}
181202

182203
/// <summary>

0 commit comments

Comments
 (0)