Skip to content

Commit

Permalink
add converters for DateOnly and TimeOnly
Browse files Browse the repository at this point in the history
  • Loading branch information
Edward Miller committed Apr 23, 2024
1 parent 3f9472b commit 2f0f12b
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/Controls/src/Core/DateOnlyConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#if NET6_0_OR_GREATER
using System;
using System.ComponentModel;
using System.Globalization;

namespace Microsoft.Maui.Controls
{
internal class DateOnlyConverter : TypeConverter, IExtendedTypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
=> sourceType == typeof(string) || sourceType == typeof(DateTime);

public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
=> destinationType == typeof(string) || destinationType == typeof(DateTime);

object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
{
if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
{
return DateOnly.FromDateTime(result);
}
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(DateOnly)}");
}

public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object? value)
{
if (value is DateTime dateTime)
{
return DateOnly.FromDateTime(dateTime);
}
if (value is string stringValue && DateTime.TryParse(stringValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out var result))
{
return DateOnly.FromDateTime(result);
}
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(DateOnly)}");
}

public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
{
if (value is DateOnly dateOnly)
{
if (destinationType == typeof(string))
{
return dateOnly.ToString(culture);
}
if (destinationType == typeof(DateTime))
{
return dateOnly.ToDateTime(TimeOnly.MinValue);
}
}
throw new NotSupportedException($"Cannot convert \"{value}\" into {destinationType}");
}
}
}
#endif
3 changes: 3 additions & 0 deletions src/Controls/src/Core/DatePicker/DatePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ public DatePicker()
}

/// <include file="../../docs/Microsoft.Maui.Controls/DatePicker.xml" path="//Member[@MemberName='Date']/Docs/*" />
#if NET6_0_OR_GREATER
[System.ComponentModel.TypeConverter(typeof(DateOnlyConverter))]
#endif
public DateTime Date
{
get { return (DateTime)GetValue(DateProperty); }
Expand Down
55 changes: 55 additions & 0 deletions src/Controls/src/Core/TimeOnlyConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#if NET6_0_OR_GREATER
using System;
using System.ComponentModel;
using System.Globalization;

namespace Microsoft.Maui.Controls
{
internal class TimeOnlyToTimeSpanConverter : TypeConverter, IExtendedTypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
=> sourceType == typeof(string) || sourceType == typeof(TimeOnly);

public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
=> destinationType == typeof(string) || destinationType == typeof(TimeSpan);

object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
{
if (TimeOnly.TryParse(value, out var result))
{
return result.ToTimeSpan();
}
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(TimeSpan)}");
}

public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object? value)
{
if (value is TimeOnly timeOnly)
{
return timeOnly.ToTimeSpan();
}
if (value is string stringValue && TimeOnly.TryParse(stringValue, out var result))
{
return result.ToTimeSpan();
}
throw new NotSupportedException($"Cannot convert \"{value}\" into {typeof(TimeSpan)}");
}

public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
{
if (value is TimeSpan timeSpan)
{
if (destinationType == typeof(string))
{
return timeSpan.ToString();
}
if (destinationType == typeof(TimeOnly))
{
return TimeOnly.FromTimeSpan(timeSpan);
}
}
throw new NotSupportedException($"Cannot convert \"{value}\" into {destinationType}");
}
}
}
#endif
3 changes: 3 additions & 0 deletions src/Controls/src/Core/TimePicker/TimePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ public double CharacterSpacing
}

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

0 comments on commit 2f0f12b

Please sign in to comment.