Skip to content

Commit

Permalink
Merge pull request #49 from webappsuk/schedules
Browse files Browse the repository at this point in the history
  • Loading branch information
thargy authored Sep 6, 2017
2 parents 46181ee + 0d42f1e commit a4e433f
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 61 deletions.
73 changes: 13 additions & 60 deletions Scheduling/Schedules/PeriodicSchedule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,54 +93,7 @@ public class PeriodicSchedule : FunctionalSchedule, IEquatable<PeriodicSchedule>
/// The weekday.
/// </summary>
public readonly WeekDay WeekDay;

/// <summary>
/// Initializes a new instance of the <see cref="PeriodicSchedule" /> class, used by configuration system.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="month">The month.</param>
/// <param name="week">The week.</param>
/// <param name="day">The day.</param>
/// <param name="weekDay">The week day.</param>
/// <param name="hour">The hour.</param>
/// <param name="minute">The minute.</param>
/// <param name="second">The second.</param>
/// <param name="minimumTimeSpan">The minimum gap.</param>
/// <param name="calendar">The calendar ID.</param>
/// <param name="timeZone">The time zone ID.</param>
/// <param name="options">The options.</param>
[UsedImplicitly]
private PeriodicSchedule(
[CanBeNull] string name,
Month month = Month.Every,
Week week = Week.Every,
Day day = Day.Every,
WeekDay weekDay = WeekDay.Every,
Hour hour = Hour.Zeroth,
Minute minute = Minute.Zeroth,
Second second = Second.Zeroth,
TimeSpan minimumTimeSpan = default(TimeSpan),
[CanBeNull] string calendar = null,
[CanBeNull] string timeZone = null,
ScheduleOptions options = ScheduleOptions.None)
: this(
month,
week,
day,
weekDay,
hour,
minute,
second,
minimumTimeSpan < TimeSpan.Zero ? Duration.Zero : Duration.FromTimeSpan(minimumTimeSpan),
// ReSharper disable PossibleNullReferenceException, AssignNullToNotNullAttribute
string.IsNullOrWhiteSpace(calendar) ? CalendarSystem.Iso : CalendarSystem.ForId(calendar),
string.IsNullOrWhiteSpace(timeZone) ? DateTimeZone.Utc : TimeHelpers.DateTimeZoneProvider[timeZone],
// ReSharper restore PossibleNullReferenceException, AssignNullToNotNullAttribute
options,
name)
{
}


/// <summary>
/// Initializes a new instance of the <see cref="PeriodicSchedule" /> class.
/// </summary>
Expand All @@ -152,8 +105,8 @@ private PeriodicSchedule(
/// <param name="minute">The minute.</param>
/// <param name="second">The second.</param>
/// <param name="minimumGap">The minimum gap.</param>
/// <param name="calendarSystem">The calendar.</param>
/// <param name="dateTimeZone">The time zone.</param>
/// <param name="calendar">The calendar.</param>
/// <param name="timeZone">The time zone.</param>
/// <param name="options">The options.</param>
public PeriodicSchedule(
Month month = Month.Every,
Expand All @@ -164,8 +117,8 @@ public PeriodicSchedule(
Minute minute = Minute.Zeroth,
Second second = Second.Zeroth,
Duration minimumGap = default(Duration),
[CanBeNull] CalendarSystem calendarSystem = null,
[CanBeNull] DateTimeZone dateTimeZone = null,
[CanBeNull] CalendarSystem calendar = null,
[CanBeNull] DateTimeZone timeZone = null,
ScheduleOptions options = ScheduleOptions.None)
: this(
month,
Expand All @@ -177,8 +130,8 @@ public PeriodicSchedule(
second,
minimumGap < Duration.Zero ? Duration.Zero : minimumGap,
// ReSharper disable AssignNullToNotNullAttribute
calendarSystem ?? CalendarSystem.Iso,
dateTimeZone ?? DateTimeZone.Utc,
calendar ?? CalendarSystem.Iso,
timeZone ?? DateTimeZone.Utc,
// ReSharper restore AssignNullToNotNullAttribute
options,
null)
Expand All @@ -197,8 +150,8 @@ public PeriodicSchedule(
/// <param name="minute">The minute.</param>
/// <param name="second">The second.</param>
/// <param name="minimumGap">The minimum gap.</param>
/// <param name="calendarSystem">The calendar.</param>
/// <param name="dateTimeZone">The time zone.</param>
/// <param name="calendar">The calendar.</param>
/// <param name="timeZone">The time zone.</param>
/// <param name="options">The options.</param>
public PeriodicSchedule(
[CanBeNull] string name,
Expand All @@ -210,8 +163,8 @@ public PeriodicSchedule(
Minute minute = Minute.Zeroth,
Second second = Second.Zeroth,
Duration minimumGap = default(Duration),
[CanBeNull] CalendarSystem calendarSystem = null,
[CanBeNull] DateTimeZone dateTimeZone = null,
[CanBeNull] CalendarSystem calendar = null,
[CanBeNull] DateTimeZone timeZone = null,
ScheduleOptions options = ScheduleOptions.None)
: this(
month,
Expand All @@ -223,8 +176,8 @@ public PeriodicSchedule(
second,
minimumGap < Duration.Zero ? Duration.Zero : minimumGap,
// ReSharper disable AssignNullToNotNullAttribute
calendarSystem ?? CalendarSystem.Iso,
dateTimeZone ?? DateTimeZone.Utc,
calendar ?? CalendarSystem.Iso,
timeZone ?? DateTimeZone.Utc,
// ReSharper restore AssignNullToNotNullAttribute
options,
name)
Expand Down
11 changes: 10 additions & 1 deletion Scheduling/Test/app.config
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,20 @@
<add name="month" value="EveryTwoMonths" />
<add name="day" value="First" />
<add name="hour" value="Third" />
<add name="minimumTimeSpan" value="00:00:02" />
<add name="minimumGap" value="00:00:02" />
<add name="calendar" value="Gregorian 4" />
<add name="timeZone" value="Europe/London" />
</parameters>
</add>
<!-- Ambiguity between PeriodicSchedule CTORs when not specifying the calendar and timeZone parameters -->
<add name="EveryMonth" type="WebApplications.Utilities.Scheduling.Schedules.PeriodicSchedule, WebApplications.Utilities.Scheduling">
<parameters>
<add name="month" value="Every" />
<add name="day" value="First" />
<add name="hour" value="Third" />
<add name="minimumGap" value="00:00:02" />
</parameters>
</add>
<add name="Aggregate" type="WebApplications.Utilities.Scheduling.Schedules.AggregateSchedule, WebApplications.Utilities.Scheduling">
<parameters>
<add name="schedule1" value="OneOff" />
Expand Down
123 changes: 123 additions & 0 deletions Utilities/Converters/CalendarSystemConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#region © Copyright Web Applications (UK) Ltd, 2017. All rights reserved.
// Copyright (c) 2017, Web Applications UK Ltd
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Web Applications UK Ltd nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL WEB APPLICATIONS UK LTD BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using System.ComponentModel;
using System.Globalization;
using NodaTime;
using WebApplications.Utilities.Annotations;

namespace WebApplications.Utilities.Converters
{
/// <summary>
/// Providers methods for converting types to/from the <see cref="CalendarSystem"/> type.
/// </summary>
public class CalendarSystemConverter : TypeConverter
{
/// <summary>
/// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
/// </summary>
/// <returns>
/// true if this converter can perform the conversion; otherwise, false.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="sourceType">A <see cref="T:System.Type"/> that represents the type you want to convert from. </param>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;

return base.CanConvertFrom(context, sourceType);
}

/// <summary>
/// Converts the given object to the type of this converter, using the specified context and culture information.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the converted value.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="culture">The <see cref="T:System.Globalization.CultureInfo"/> to use as the current culture. </param>
/// <param name="value">The <see cref="T:System.Object"/> to convert. </param>
/// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception>
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string @string)
{
CalendarSystem calendarSystem = CalendarSystem.ForId(@string);
return calendarSystem;
}

return base.ConvertFrom(context, culture, value);
}

/// <summary>
/// Returns whether this converter can convert the object to the specified type, using the specified context.
/// </summary>
/// <returns>
/// true if this converter can perform the conversion; otherwise, false.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="destinationType">A <see cref="T:System.Type"/> that represents the type you want to convert to. </param>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;

return base.CanConvertTo(context, destinationType);
}

/// <summary>
/// Converts the given value object to the specified type, using the specified context and culture information.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the converted value.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="culture">A <see cref="T:System.Globalization.CultureInfo"/>. If null is passed, the current culture is assumed. </param>
/// <param name="value">The <see cref="T:System.Object"/> to convert. </param>
/// <param name="destinationType">The <see cref="T:System.Type"/> to convert the <paramref name="value"/> parameter to. </param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="destinationType"/> parameter is null. </exception>
/// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception>
public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture,
[NotNull] object value,
Type destinationType)
{
if (value == null) throw new ArgumentNullException(nameof(value));
if (destinationType == null) throw new ArgumentNullException(nameof(destinationType));

CalendarSystem calendarSystem = (CalendarSystem)value;

if (destinationType == typeof(string))
return calendarSystem.Id;

return base.ConvertTo(context, culture, value, destinationType);
}
}
}
120 changes: 120 additions & 0 deletions Utilities/Converters/DateTimeZoneConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#region © Copyright Web Applications (UK) Ltd, 2017. All rights reserved.
// Copyright (c) 2017, Web Applications UK Ltd
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of Web Applications UK Ltd nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL WEB APPLICATIONS UK LTD BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using System.ComponentModel;
using System.Globalization;
using NodaTime;
using WebApplications.Utilities.Annotations;

namespace WebApplications.Utilities.Converters
{
/// <summary>
/// Providers methods for converting types to/from the <see cref="DateTimeZone"/> type.
/// </summary>
public class DateTimeZoneConverter : TypeConverter
{
/// <summary>
/// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
/// </summary>
/// <returns>
/// true if this converter can perform the conversion; otherwise, false.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="sourceType">A <see cref="T:System.Type"/> that represents the type you want to convert from. </param>
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;

return base.CanConvertFrom(context, sourceType);
}

/// <summary>
/// Converts the given object to the type of this converter, using the specified context and culture information.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the converted value.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="culture">The <see cref="T:System.Globalization.CultureInfo"/> to use as the current culture. </param>
/// <param name="value">The <see cref="T:System.Object"/> to convert. </param>
/// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception>
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string @string)
return TimeHelpers.DateTimeZoneProvider[@string];

return base.ConvertFrom(context, culture, value);
}

/// <summary>
/// Returns whether this converter can convert the object to the specified type, using the specified context.
/// </summary>
/// <returns>
/// true if this converter can perform the conversion; otherwise, false.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="destinationType">A <see cref="T:System.Type"/> that represents the type you want to convert to. </param>
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;

return base.CanConvertTo(context, destinationType);
}

/// <summary>
/// Converts the given value object to the specified type, using the specified context and culture information.
/// </summary>
/// <returns>
/// An <see cref="T:System.Object"/> that represents the converted value.
/// </returns>
/// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"/> that provides a format context. </param>
/// <param name="culture">A <see cref="T:System.Globalization.CultureInfo"/>. If null is passed, the current culture is assumed. </param>
/// <param name="value">The <see cref="T:System.Object"/> to convert. </param>
/// <param name="destinationType">The <see cref="T:System.Type"/> to convert the <paramref name="value"/> parameter to. </param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="destinationType"/> parameter is null. </exception>
/// <exception cref="T:System.NotSupportedException">The conversion cannot be performed. </exception>
public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture,
[NotNull] object value,
Type destinationType)
{
if (value == null) throw new ArgumentNullException(nameof(value));
if (destinationType == null) throw new ArgumentNullException(nameof(destinationType));

DateTimeZone dateTimeZone = (DateTimeZone)value;

if (destinationType == typeof(string))
return dateTimeZone.Id;

return base.ConvertTo(context, culture, value, destinationType);
}
}
}
Loading

0 comments on commit a4e433f

Please sign in to comment.