Skip to content

Commit 2f0f12b

Browse files
author
Edward Miller
committed
add converters for DateOnly and TimeOnly
1 parent 3f9472b commit 2f0f12b

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#if NET6_0_OR_GREATER
2+
using System;
3+
using System.ComponentModel;
4+
using System.Globalization;
5+
6+
namespace Microsoft.Maui.Controls
7+
{
8+
internal class DateOnlyConverter : TypeConverter, IExtendedTypeConverter
9+
{
10+
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
11+
=> sourceType == typeof(string) || sourceType == typeof(DateTime);
12+
13+
public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
14+
=> destinationType == typeof(string) || destinationType == typeof(DateTime);
15+
16+
object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
17+
{
18+
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
19+
{
20+
return DateOnly.FromDateTime(result);
21+
}
22+
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(DateOnly)}");
23+
}
24+
25+
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object? value)
26+
{
27+
if (value is DateTime dateTime)
28+
{
29+
return DateOnly.FromDateTime(dateTime);
30+
}
31+
if (value is string stringValue && DateTime.TryParse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
32+
{
33+
return DateOnly.FromDateTime(result);
34+
}
35+
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(DateOnly)}");
36+
}
37+
38+
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
39+
{
40+
if (value is DateOnly dateOnly)
41+
{
42+
if (destinationType == typeof(string))
43+
{
44+
return dateOnly.ToString(culture);
45+
}
46+
if (destinationType == typeof(DateTime))
47+
{
48+
return dateOnly.ToDateTime(TimeOnly.MinValue);
49+
}
50+
}
51+
throw new NotSupportedException($"Cannot convert \"{value}\" into {destinationType}");
52+
}
53+
}
54+
}
55+
#endif

src/Controls/src/Core/DatePicker/DatePicker.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ public DatePicker()
5252
}
5353

5454
/// <include file="../../docs/Microsoft.Maui.Controls/DatePicker.xml" path="//Member[@MemberName='Date']/Docs/*" />
55+
#if NET6_0_OR_GREATER
56+
[System.ComponentModel.TypeConverter(typeof(DateOnlyConverter))]
57+
#endif
5558
public DateTime Date
5659
{
5760
get { return (DateTime)GetValue(DateProperty); }
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#if NET6_0_OR_GREATER
2+
using System;
3+
using System.ComponentModel;
4+
using System.Globalization;
5+
6+
namespace Microsoft.Maui.Controls
7+
{
8+
internal class TimeOnlyToTimeSpanConverter : TypeConverter, IExtendedTypeConverter
9+
{
10+
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
11+
=> sourceType == typeof(string) || sourceType == typeof(TimeOnly);
12+
13+
public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
14+
=> destinationType == typeof(string) || destinationType == typeof(TimeSpan);
15+
16+
object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
17+
{
18+
if (TimeOnly.TryParse(value, out var result))
19+
{
20+
return result.ToTimeSpan();
21+
}
22+
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(TimeSpan)}");
23+
}
24+
25+
public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object? value)
26+
{
27+
if (value is TimeOnly timeOnly)
28+
{
29+
return timeOnly.ToTimeSpan();
30+
}
31+
if (value is string stringValue && TimeOnly.TryParse(stringValue, out var result))
32+
{
33+
return result.ToTimeSpan();
34+
}
35+
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(TimeSpan)}");
36+
}
37+
38+
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
39+
{
40+
if (value is TimeSpan timeSpan)
41+
{
42+
if (destinationType == typeof(string))
43+
{
44+
return timeSpan.ToString();
45+
}
46+
if (destinationType == typeof(TimeOnly))
47+
{
48+
return TimeOnly.FromTimeSpan(timeSpan);
49+
}
50+
}
51+
throw new NotSupportedException($"Cannot convert \"{value}\" into {destinationType}");
52+
}
53+
}
54+
}
55+
#endif

src/Controls/src/Core/TimePicker/TimePicker.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public double CharacterSpacing
6767
}
6868

6969
/// <include file="../../docs/Microsoft.Maui.Controls/TimePicker.xml" path="//Member[@MemberName='Time']/Docs/*" />
70+
#if NET6_0_OR_GREATER
71+
[System.ComponentModel.TypeConverter(typeof(TimeOnlyConverter))]
72+
#endif
7073
public TimeSpan Time
7174
{
7275
get { return (TimeSpan)GetValue(TimeProperty); }

0 commit comments

Comments
 (0)