Skip to content

Commit

Permalink
Add support for DateOnly and TimeOnly through implicit operator conve…
Browse files Browse the repository at this point in the history
…rsion

Fixes #115
  • Loading branch information
0xced committed May 31, 2024
1 parent b2249c0 commit 0990c66
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Kiota's `Date` and `Time` types are interchangeable with the system `DateOnly` and `TimeOnly` types through implicit conversion operators.

## [1.9.4] - 2024-05-31

### Changed
Expand Down
90 changes: 88 additions & 2 deletions Microsoft.Kiota.Abstractions.Tests/RequestInformationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,52 @@ public void SetsPathParametersOfTimeType()
// Assert
Assert.Contains($"%24time=06%3A00%3A00", requestInfo.URI.OriginalString);
}
#if NET6_0_OR_GREATER
[Fact]
public void SetsPathParametersOfDateOnlyType()
{
// Arrange as the request builders would
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/users{?%24date}"
};

// Act
var date = new DateOnly(2023, 10, 26);
var pathParameters = new Dictionary<string, object>
{
{ "%24date", date }
};

requestInfo.PathParameters = pathParameters;

// Assert
Assert.Contains($"%24date=2023-10-26", requestInfo.URI.OriginalString);
}
[Fact]
public void SetsPathParametersOfTimeOnlyType()
{
// Arrange as the request builders would
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/users{?%24time}"
};

// Act
var time = new TimeOnly(6, 0, 0);
var pathParameters = new Dictionary<string, object>
{
{ "%24time", time }
};

requestInfo.PathParameters = pathParameters;

// Assert
Assert.Contains($"%24time=06%3A00%3A00", requestInfo.URI.OriginalString);
}
#endif
[Fact]
public void CurrentCultureDoesNotAffectTimeSerialization()
{
Expand Down Expand Up @@ -663,14 +709,54 @@ public void SetsTimeValuesInQueryParameters()
};

// Act
var date1 = new Time(10, 0, 0);
var date2 = new Time(11, 1, 1);
var time1 = new Time(10, 0, 0);
var time2 = new Time(11, 1, 1);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { time1, time2 } });

// Assert
Assert.Equal("http://localhost/me?items=10%3A00%3A00,11%3A01%3A01", requestInfo.URI.OriginalString);
}

#if NET6_0_OR_GREATER
[Fact]
public void SetsDateOnlyValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
Date date1 = new DateOnly(2022, 8, 1);
DateOnly date2 = new Date(2022, 8, 2);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { date1, date2 } });

// Assert
Assert.Equal("http://localhost/me?items=2022-08-01,2022-08-02", requestInfo.URI.OriginalString);
}

[Fact]
public void SetsTimeOnlyValuesInQueryParameters()
{
var requestInfo = new RequestInformation
{
HttpMethod = Method.GET,
UrlTemplate = "http://localhost/me{?items}"
};

// Act
Time time1 = new TimeOnly(10, 0, 0);
TimeOnly time2 = new Time(11, 1, 1);

requestInfo.AddQueryParameters(new GetQueryParameters { Items = new object[] { time1, time2 } });

// Assert
Assert.Equal("http://localhost/me?items=10%3A00%3A00,11%3A01%3A01", requestInfo.URI.OriginalString);
}
#endif

[Fact]
public void SetsGuidValuesInQueryParameters()
Expand Down
16 changes: 16 additions & 0 deletions src/Date.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ namespace Microsoft.Kiota.Abstractions
/// </summary>
public struct Date
{
#if NET6_0_OR_GREATER
/// <summary>
/// Converts the supplied <see cref="DateOnly"/> parameter to <see cref="Date"/>.
/// </summary>
/// <param name="date">The <see cref="DateOnly"/> to be converted.</param>
/// <returns>A new <see cref="Date"/> structure whose years, months and days are equal to those of the supplied date.</returns>
public static implicit operator Date(DateOnly date) => new(date.Year, date.Month, date.Day);

/// <summary>
/// Converts the supplied <see cref="Date"/> parameter to <see cref="DateOnly"/>.
/// </summary>
/// <param name="date">The <see cref="Date"/> to be converted.</param>
/// <returns>A new <see cref="DateOnly"/> structure whose years, months and days are equal to those of the supplied date.</returns>
public static implicit operator DateOnly(Date date) => new(date.Year, date.Month, date.Day);
#endif

/// <summary>
/// Create a new Date object from a <see cref="DateTime"/> object
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/RequestInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ public Uri URI
bool boolean => boolean.ToString().ToLower(),// pass in a lowercase string as the final url will be uppercase due to the way ToString() works for booleans
DateTimeOffset dateTimeOffset => dateTimeOffset.ToString("o"),// Default to ISO 8601 for datetimeoffsets in the url.
DateTime dateTime => dateTime.ToString("o"),// Default to ISO 8601 for datetimes in the url.
#if NET6_0_OR_GREATER
DateOnly dateOnly => dateOnly.ToString("yyyy-MM-dd"),// Default to ISO 8601 for dateonlys in the url.
TimeOnly timeOnly => timeOnly.ToString(@"HH\:mm\:ss"),// Default to ISO 8601 for timeonlys in the url.
#endif
Guid guid => guid.ToString("D"),// Default of 32 digits separated by hyphens
Date date => date.ToString(), //Default to string format of the custom date object
Time time => time.ToString(), //Default to string format of the custom time object
Expand Down
15 changes: 15 additions & 0 deletions src/Time.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ namespace Microsoft.Kiota.Abstractions
/// </summary>
public struct Time
{
#if NET6_0_OR_GREATER
/// <summary>
/// Converts the supplied <see cref="TimeOnly"/> parameter to <see cref="Time"/>.
/// </summary>
/// <param name="time">The <see cref="TimeOnly"/> to be converted.</param>
/// <returns>A new <see cref="Time"/> structure whose hours, minutes, seconds and milliseconds are equal to those of the supplied time.</returns>
public static implicit operator Time(TimeOnly time) => new(new DateTime(1, 1, 1, time.Hour, time.Minute, time.Second, time.Millisecond));

/// <summary>
/// Converts the supplied <see cref="Time"/> parameter to <see cref="TimeOnly"/>.
/// </summary>
/// <param name="time">The <see cref="Time"/> to be converted.</param>
/// <returns>A new <see cref="TimeOnly"/> structure whose hours, minutes, seconds and milliseconds are equal to those of the supplied time.</returns>
public static implicit operator TimeOnly(Time time) => new(time.DateTime.Hour, time.DateTime.Minute, time.DateTime.Second, time.DateTime.Millisecond);
#endif
/// <summary>
/// Create a new Time from hours, minutes, and seconds.
/// </summary>
Expand Down

0 comments on commit 0990c66

Please sign in to comment.