Skip to content

Commit 4dcee4d

Browse files
authored
Add support for DateOnly and TimeOnly on .Net 6 (#1732). (#1734)
1 parent 1ac7dfd commit 4dcee4d

File tree

2 files changed

+91
-21
lines changed

2 files changed

+91
-21
lines changed

src/System.CommandLine.Tests/Binding/TypeConversionTests.cs

+59-17
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
// Copyright (c) .NET Foundation and contributors. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using FluentAssertions;
45
using System.Collections;
56
using System.Collections.Generic;
67
using System.CommandLine.Utility;
78
using System.IO;
8-
using FluentAssertions;
99
using System.Linq;
10-
using Xunit;
1110
using System.Net;
11+
using Xunit;
1212

1313
namespace System.CommandLine.Tests.Binding
1414
{
@@ -230,7 +230,7 @@ public void Nullable_bool_parses_as_false_when_the_option_has_been_applied(strin
230230
public void Nullable_bool_parses_as_null_when_the_option_has_not_been_applied()
231231
{
232232
var option = new Option<bool?>("-x");
233-
233+
234234
option
235235
.Parse("")
236236
.GetValueForOption(option)
@@ -252,7 +252,7 @@ public void Generic_option_bool_parses_when_passed_to_non_generic_GetValueForOpt
252252

253253
parseResult.GetValueForOption((Option)option).Should().Be(true);
254254
}
255-
255+
256256
[Fact]
257257
public void When_exactly_one_argument_is_expected_and_none_are_provided_then_getting_value_throws()
258258
{
@@ -274,7 +274,7 @@ public void When_exactly_one_argument_is_expected_and_none_are_provided_then_get
274274
.Should()
275275
.Be("Required argument missing for option: '-x'.");
276276
}
277-
277+
278278
[Theory]
279279
[InlineData("c -a o c c")]
280280
[InlineData("c c -a o c")]
@@ -496,7 +496,7 @@ public void Values_can_be_correctly_converted_to_decimal_without_the_parser_spec
496496

497497
value.Should().Be(123.456m);
498498
}
499-
499+
500500
[Fact]
501501
public void Values_can_be_correctly_converted_to_nullable_decimal_without_the_parser_specifying_a_custom_converter()
502502
{
@@ -506,7 +506,7 @@ public void Values_can_be_correctly_converted_to_nullable_decimal_without_the_pa
506506

507507
value.Should().Be(123.456m);
508508
}
509-
509+
510510
[Fact]
511511
public void Values_can_be_correctly_converted_to_double_without_the_parser_specifying_a_custom_converter()
512512
{
@@ -516,7 +516,7 @@ public void Values_can_be_correctly_converted_to_double_without_the_parser_speci
516516

517517
value.Should().Be(123.456d);
518518
}
519-
519+
520520
[Fact]
521521
public void Values_can_be_correctly_converted_to_nullable_double_without_the_parser_specifying_a_custom_converter()
522522
{
@@ -536,7 +536,7 @@ public void Values_can_be_correctly_converted_to_float_without_the_parser_specif
536536

537537
value.Should().Be(123.456f);
538538
}
539-
539+
540540
[Fact]
541541
public void Values_can_be_correctly_converted_to_nullable_float_without_the_parser_specifying_a_custom_converter()
542542
{
@@ -557,7 +557,7 @@ public void Values_can_be_correctly_converted_to_Guid_without_the_parser_specify
557557

558558
value.Should().Be(Guid.Parse(guidString));
559559
}
560-
560+
561561
[Fact]
562562
public void Values_can_be_correctly_converted_to_nullable_Guid_without_the_parser_specifying_a_custom_converter()
563563
{
@@ -689,7 +689,7 @@ public void Values_can_be_correctly_converted_to_nullable_ushort_without_the_par
689689

690690
value.Should().Be(1234);
691691
}
692-
692+
693693
[Fact]
694694
public void Values_can_be_correctly_converted_to_sbyte_without_the_parser_specifying_a_custom_converter()
695695
{
@@ -699,7 +699,7 @@ public void Values_can_be_correctly_converted_to_sbyte_without_the_parser_specif
699699

700700
value.Should().Be(123);
701701
}
702-
702+
703703
[Fact]
704704
public void Values_can_be_correctly_converted_to_nullable_sbyte_without_the_parser_specifying_a_custom_converter()
705705
{
@@ -732,6 +732,48 @@ public void Values_can_be_correctly_converted_to_ipendpoint_without_the_parser_s
732732
}
733733
#endif
734734

735+
#if NET6_0_OR_GREATER
736+
[Fact]
737+
public void Values_can_be_correctly_converted_to_dateonly_without_the_parser_specifying_a_custom_converter()
738+
{
739+
var option = new Option<DateOnly>("-us");
740+
741+
var value = option.Parse("-us 2022-03-02").GetValueForOption(option);
742+
743+
value.Should().Be(DateOnly.Parse("2022-03-02"));
744+
}
745+
746+
[Fact]
747+
public void Values_can_be_correctly_converted_to_nullable_dateonly_without_the_parser_specifying_a_custom_converter()
748+
{
749+
var option = new Option<DateOnly?>("-x");
750+
751+
var value = option.Parse("-x 2022-03-02").GetValueForOption(option);
752+
753+
value.Should().Be(DateOnly.Parse("2022-03-02"));
754+
}
755+
756+
[Fact]
757+
public void Values_can_be_correctly_converted_to_timeonly_without_the_parser_specifying_a_custom_converter()
758+
{
759+
var option = new Option<TimeOnly>("-us");
760+
761+
var value = option.Parse("-us 12:34:56").GetValueForOption(option);
762+
763+
value.Should().Be(TimeOnly.Parse("12:34:56"));
764+
}
765+
766+
[Fact]
767+
public void Values_can_be_correctly_converted_to_nullable_timeonly_without_the_parser_specifying_a_custom_converter()
768+
{
769+
var option = new Option<TimeOnly?>("-x");
770+
771+
var value = option.Parse("-x 12:34:56").GetValueForOption(option);
772+
773+
value.Should().Be(TimeOnly.Parse("12:34:56"));
774+
}
775+
#endif
776+
735777
[Fact]
736778
public void Values_can_be_correctly_converted_to_byte_without_the_parser_specifying_a_custom_converter()
737779
{
@@ -741,7 +783,7 @@ public void Values_can_be_correctly_converted_to_byte_without_the_parser_specify
741783

742784
value.Should().Be(123);
743785
}
744-
786+
745787
[Fact]
746788
public void Values_can_be_correctly_converted_to_nullable_byte_without_the_parser_specifying_a_custom_converter()
747789
{
@@ -751,7 +793,7 @@ public void Values_can_be_correctly_converted_to_nullable_byte_without_the_parse
751793

752794
value.Should().Be(123);
753795
}
754-
796+
755797
[Fact]
756798
public void Values_can_be_correctly_converted_to_uint_without_the_parser_specifying_a_custom_converter()
757799
{
@@ -761,7 +803,7 @@ public void Values_can_be_correctly_converted_to_uint_without_the_parser_specify
761803

762804
value.Should().Be(1234);
763805
}
764-
806+
765807
[Fact]
766808
public void Values_can_be_correctly_converted_to_nullable_uint_without_the_parser_specifying_a_custom_converter()
767809
{
@@ -781,7 +823,7 @@ public void Values_can_be_correctly_converted_to_array_of_int_without_the_parser
781823

782824
value.Should().BeEquivalentTo(1, 2, 3);
783825
}
784-
826+
785827
[Theory]
786828
[InlineData(0, 100_000, typeof(string[]))]
787829
[InlineData(0, 3, typeof(string[]))]
@@ -793,7 +835,7 @@ public void Values_can_be_correctly_converted_to_array_of_int_without_the_parser
793835
[InlineData(0, 3, typeof(IList<string>))]
794836
[InlineData(0, 100_000, typeof(ICollection<string>))]
795837
[InlineData(0, 3, typeof(ICollection<string>))]
796-
838+
797839
[InlineData(1, 100_000, typeof(string[]))]
798840
[InlineData(1, 3, typeof(string[]))]
799841
[InlineData(1, 100_000, typeof(IEnumerable<string>))]

src/System.CommandLine/Binding/ArgumentConverter.StringConverters.cs

+32-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@ internal static partial class ArgumentConverter
2525
return false;
2626
},
2727

28+
#if NET6_0_OR_GREATER
29+
[typeof(DateOnly)] = (string input, out object? value) =>
30+
{
31+
if (DateOnly.TryParse(input, out var parsed))
32+
{
33+
value = parsed;
34+
return true;
35+
}
36+
37+
value = default;
38+
return false;
39+
},
40+
#endif
41+
2842
[typeof(DateTime)] = (string input, out object? value) =>
2943
{
3044
if (DateTime.TryParse(input, out var parsed))
@@ -63,7 +77,7 @@ internal static partial class ArgumentConverter
6377

6478
[typeof(DirectoryInfo)] = (string path, out object? value) =>
6579
{
66-
if (String.IsNullOrEmpty(path))
80+
if (string.IsNullOrEmpty(path))
6781
{
6882
value = default;
6983
return false;
@@ -86,7 +100,7 @@ internal static partial class ArgumentConverter
86100

87101
[typeof(FileInfo)] = (string path, out object? value) =>
88102
{
89-
if (String.IsNullOrEmpty(path))
103+
if (string.IsNullOrEmpty(path))
90104
{
91105
value = default;
92106
return false;
@@ -97,7 +111,7 @@ internal static partial class ArgumentConverter
97111

98112
[typeof(FileSystemInfo)] = (string path, out object? value) =>
99113
{
100-
if (String.IsNullOrEmpty(path))
114+
if (string.IsNullOrEmpty(path))
101115
{
102116
value = default;
103117
return false;
@@ -130,7 +144,7 @@ internal static partial class ArgumentConverter
130144
value = default;
131145
return false;
132146
},
133-
147+
134148
[typeof(Guid)] = (string input, out object? value) =>
135149
{
136150
if (Guid.TryParse(input, out var parsed))
@@ -205,6 +219,20 @@ internal static partial class ArgumentConverter
205219
return false;
206220
},
207221

222+
#if NET6_0_OR_GREATER
223+
[typeof(TimeOnly)] = (string input, out object? value) =>
224+
{
225+
if (TimeOnly.TryParse(input, out var parsed))
226+
{
227+
value = parsed;
228+
return true;
229+
}
230+
231+
value = default;
232+
return false;
233+
},
234+
#endif
235+
208236
[typeof(uint)] = (string token, out object? value) =>
209237
{
210238
if (uint.TryParse(token, out var uintValue))

0 commit comments

Comments
 (0)