-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add functions to get or change some parts of a date (#214)
* feat: add datepart functions returning textual values * feat: add datepart functions returning numeric values * feat: add functions to change year or month * Update the automatically generated documentation related to the list of functions and predicates --------- Co-authored-by: AppVeyor bot <[email protected]>
- Loading branch information
Showing
12 changed files
with
1,061 additions
and
289 deletions.
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
Expressif.Testing/Functions/Temporal/DatePartChangeFunctionsTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Expressif.Functions.Temporal; | ||
using Expressif.Values; | ||
|
||
namespace Expressif.Testing.Functions.Temporal; | ||
public class DatePartChangeFunctionsTest | ||
{ | ||
[Test] | ||
[TestCase(1900, 1903)] | ||
[TestCase(2000, 2000)] | ||
[TestCase(-45, 16)] | ||
[TestCase(800, 803)] | ||
[TestCase(12300, 2000)] | ||
public void ChangeOfYear_Integer_Valid(int year, int expected) | ||
=> Assert.That(new ChangeOfYear(() => expected).Evaluate(year), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", 1903, "1903-01-01")] | ||
[TestCase("2000-01-01", 2000, "2000-01-01")] | ||
[TestCase("800-01-01", 2000, "2000-01-01")] | ||
[TestCase("2004-02-29", 2008, "2008-02-29")] | ||
[TestCase("2004-02-29", 2005, "2005-02-28")] | ||
public void ChangeOfYear_DateTime_Valid(DateTime dt, int newYear, DateTime expected) | ||
=> Assert.That(new ChangeOfYear(() => newYear).Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01", 1903, "1903-01")] | ||
[TestCase("2000-01", 2000, "2000-01")] | ||
[TestCase("0800-01", 2000, "2000-01")] | ||
public void ChangeOfYear_YearMonth_Valid(YearMonth yearMonth, int newYear, YearMonth expected) | ||
=> Assert.That(new ChangeOfYear(() => newYear).Evaluate(yearMonth), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", 3, "1900-03-01")] | ||
[TestCase("2000-01-31", 3, "2000-03-31")] | ||
[TestCase("2000-01-31", 4, "2000-04-30")] | ||
[TestCase("2000-01-31", 2, "2000-02-29")] | ||
[TestCase("2001-01-31", 2, "2001-02-28")] | ||
public void ChangeOfMonth_DateTime_Valid(DateTime dt, int newMonth, DateTime expected) | ||
=> Assert.That(new ChangeOfMonth(() => newMonth).Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", -1)] | ||
[TestCase("1900-01-01", 0)] | ||
[TestCase("1900-01-01", 13)] | ||
public void ChangeOfMonth_DateTime_Invalid(DateTime dt, int newMonth) | ||
=> Assert.That(new ChangeOfMonth(() => newMonth).Evaluate(dt)!.Equals(null), Is.True); | ||
|
||
[Test] | ||
[TestCase("1900-01", 3, "1900-03")] | ||
[TestCase("1900-01", 3, "1900-03")] | ||
[TestCase("2000-01", 1, "2000-01")] | ||
[TestCase("0800-01", 3, "0800-03")] | ||
public void ChangeOfMonth_YearMonth_Valid(YearMonth yearMonth, int newMonth, YearMonth expected) | ||
=> Assert.That(new ChangeOfMonth(() => newMonth).Evaluate(yearMonth), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01", -1)] | ||
[TestCase("1900-01", 0)] | ||
[TestCase("1900-01", 13)] | ||
public void ChangeOfMonth_YearMonth_Invalid(YearMonth yearMonth, int newMonth) | ||
=> Assert.That(new ChangeOfMonth(() => newMonth).Evaluate(yearMonth)!.Equals(null), Is.True); | ||
} |
91 changes: 91 additions & 0 deletions
91
Expressif.Testing/Functions/Temporal/DatePartNumericFunctionsTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Expressif.Functions.Temporal; | ||
using Expressif.Values; | ||
|
||
namespace Expressif.Testing.Functions.Temporal; | ||
public class DatePartNumericFunctionsTest | ||
{ | ||
[Test] | ||
[TestCase(1900, 1900)] | ||
[TestCase(2000, 2000)] | ||
[TestCase(-45, -0045)] | ||
[TestCase(800, 800)] | ||
[TestCase(12300, 12300)] | ||
public void YearOfEra_Integer_Valid(int year, int expected) | ||
=> Assert.That(new YearOfEra().Evaluate(year), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", 1900)] | ||
[TestCase("2000-01-01", 2000)] | ||
[TestCase("800-01-01", 800)] | ||
public void YearOfEra_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new YearOfEra().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01", 1900)] | ||
[TestCase("2000-01", 2000)] | ||
[TestCase("0800-01", 800)] | ||
public void YearOfEra_YearMonth_Valid(YearMonth yearMonth, int expected) | ||
=> Assert.That(new YearOfEra().Evaluate(yearMonth), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase(1)] | ||
[TestCase(10)] | ||
public void MonthOfYear_Integer_Valid(int month) | ||
=> Assert.That(new MonthOfYear().Evaluate(month), Is.Null); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", 1)] | ||
[TestCase("2000-10-01", 10)] | ||
[TestCase("800-03-01", 3)] | ||
public void MonthOfYear_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new MonthOfYear().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01", 1)] | ||
[TestCase("2000-10", 10)] | ||
[TestCase("0800-03", 3)] | ||
public void MonthOfYear_YearMonth_Valid(YearMonth yearMonth, int expected) | ||
=> Assert.That(new MonthOfYear().Evaluate(yearMonth), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("2000-01-01", 6)] | ||
[TestCase("2000-01-02", 7)] | ||
[TestCase("2000-01-03", 1)] | ||
public void DayOfWeek_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new Expressif.Functions.Temporal.DayOfWeek().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", 1)] | ||
[TestCase("2000-10-28", 28)] | ||
[TestCase("800-03-17", 17)] | ||
public void DayOfMonth_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new DayOfMonth().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", 1)] | ||
[TestCase("2000-02-01", 32)] | ||
[TestCase("800-03-17", 77)] | ||
public void DayOfYear_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new DayOfYear().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1999-12-31", 362)] | ||
[TestCase("2000-01-01", 363)] | ||
[TestCase("2000-01-02", 364)] | ||
[TestCase("2000-01-03", 001)] | ||
public void IsoDayOfYear_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new IsoDayOfYear().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1999-12-31", 52)] | ||
[TestCase("2000-01-01", 52)] | ||
[TestCase("2000-01-02", 52)] | ||
[TestCase("2000-01-03", 01)] | ||
public void IsoWeekOfYear_DateTime_Valid(DateTime dt, int expected) | ||
=> Assert.That(new IsoWeekOfYear().Evaluate(dt), Is.EqualTo(expected)); | ||
} |
83 changes: 83 additions & 0 deletions
83
Expressif.Testing/Functions/Temporal/DatePartTextualFunctionsTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Expressif.Functions.Temporal; | ||
using Expressif.Values; | ||
|
||
namespace Expressif.Testing.Functions.Temporal; | ||
public class DatePartTextualFunctionsTest | ||
{ | ||
[Test] | ||
[TestCase(1900, "1900")] | ||
[TestCase(2000, "2000")] | ||
[TestCase(-45, "-0045")] | ||
[TestCase(800, "0800")] | ||
[TestCase(12300, "12300")] | ||
public void Year_Integer_Valid(int year, string expected) | ||
=> Assert.That(new Year().Evaluate(year), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", "1900")] | ||
[TestCase("2000-01-01", "2000")] | ||
[TestCase("800-01-01", "0800")] | ||
public void Year_DateTime_Valid(DateTime dt, string expected) | ||
=> Assert.That(new Year().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01", "1900")] | ||
[TestCase("2000-01", "2000")] | ||
[TestCase("0800-01", "0800")] | ||
public void Year_YearMonth_Valid(YearMonth yearMonth, string expected) | ||
=> Assert.That(new Year().Evaluate(yearMonth), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase(1)] | ||
[TestCase(10)] | ||
public void Month_Integer_Valid(int month) | ||
=> Assert.That(new Month().Evaluate(month), Is.Null); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", "01")] | ||
[TestCase("2000-10-01", "10")] | ||
[TestCase("800-03-01", "03")] | ||
public void Month_DateTime_Valid(DateTime dt, string expected) | ||
=> Assert.That(new Month().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01", "01")] | ||
[TestCase("2000-10", "10")] | ||
[TestCase("0800-03", "03")] | ||
public void Month_YearMonth_Valid(YearMonth yearMonth, string expected) | ||
=> Assert.That(new Month().Evaluate(yearMonth), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1900-01-01", "01-01")] | ||
[TestCase("2000-10-01", "10-01")] | ||
[TestCase("800-03-17", "03-17")] | ||
public void MonthDay_DateTime_Valid(DateTime dt, string expected) | ||
=> Assert.That(new MonthDay().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("2000-01-01", "1999-W52")] | ||
[TestCase("2000-01-08", "2000-W01")] | ||
public void IsoYearWeek_DateTime_Valid(DateTime dt, string expected) | ||
=> Assert.That(new IsoYearWeek().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1999-12-31", "1999-W52-5")] | ||
[TestCase("2000-01-01", "1999-W52-6")] | ||
[TestCase("2000-01-02", "1999-W52-7")] | ||
[TestCase("2000-01-03", "2000-W01-1")] | ||
public void IsoYearWeekDay_DateTime_Valid(DateTime dt, string expected) | ||
=> Assert.That(new IsoYearWeekDay().Evaluate(dt), Is.EqualTo(expected)); | ||
|
||
[Test] | ||
[TestCase("1999-12-31", "1999-362")] | ||
[TestCase("2000-01-01", "1999-363")] | ||
[TestCase("2000-01-02", "1999-364")] | ||
[TestCase("2000-01-03", "2000-001")] | ||
public void IsoYearDay_DateTime_Valid(DateTime dt, string expected) | ||
=> Assert.That(new IsoYearDay().Evaluate(dt), Is.EqualTo(expected)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Expressif.Functions.Special; | ||
using Expressif.Values; | ||
using Expressif.Values.Casters; | ||
using Expressif.Values.Special; | ||
|
||
namespace Expressif.Functions.Temporal; | ||
public abstract class BaseDatePartChangeFunction : BaseTemporalFunction | ||
{ | ||
protected override object? EvaluateUncasted(object value) | ||
{ | ||
if (new Null().Equals(value)) | ||
return EvaluateNull(); | ||
|
||
if (new IntegerCaster().TryCast(value, out var integer)) | ||
return EvaluateInteger(integer); | ||
|
||
if (new YearMonthCaster().TryCast(value, out var yearMonth)) | ||
return EvaluateYearMonth(yearMonth); | ||
|
||
if (new DateTimeCaster().TryCast(value, out var dateTime)) | ||
return EvaluateDateTime(dateTime); | ||
|
||
return null; | ||
} | ||
|
||
protected virtual object? EvaluateInteger(int numeric) => null; | ||
protected virtual object? EvaluateYearMonth(YearMonth yearMonth) => null; | ||
} | ||
|
||
/// <summary> | ||
/// returns a temporal value corresponding to the same day and month of the argument value but of the year passed as the parameter. | ||
/// If the original date was the 29th of February and the year passed as a parameter is not a leap year then it returns the 28th of February. | ||
/// </summary> | ||
public class ChangeOfYear : BaseDatePartNumericFunction | ||
{ | ||
public Func<int> Year { get; } | ||
public ChangeOfYear(Func<int> year) | ||
=> Year = year; | ||
|
||
protected override object EvaluateDateTime(DateTime value) | ||
{ | ||
var newYear = Year.Invoke(); | ||
if (newYear < 1 || newYear > 9999) | ||
return new Null(); | ||
var newDay = value.Month == 2 && value.Day == 29 && !DateTime.IsLeapYear(newYear) ? 28 : value.Day; | ||
return new DateTime(newYear, value.Month, newDay, value.Hour, value.Minute, value.Second, value.Millisecond); | ||
} | ||
protected override object? EvaluateInteger(int numeric) => Year.Invoke(); | ||
protected override object? EvaluateYearMonth(YearMonth yearMonth) => new YearMonth(Year.Invoke(), yearMonth.Month); | ||
} | ||
|
||
/// <summary> | ||
/// returns a temporal value corresponding to the same day and year of the argument value but of the month passed as the parameter. | ||
/// If the original day is 29, 30, or 31 and the new month passed as a parameter has fewer days then it returns the last day of the corresponding month. | ||
/// </summary> | ||
public class ChangeOfMonth : BaseDatePartChangeFunction | ||
{ | ||
public Func<int> Month { get; } | ||
public ChangeOfMonth(Func<int> month) | ||
=> Month = month; | ||
|
||
protected override object EvaluateDateTime(DateTime value) | ||
{ | ||
var newMonth = Month.Invoke(); | ||
if (newMonth < 1 || newMonth > 12) | ||
return new Null(); | ||
var lastDayOfMonth = new DateTime(value.Year, newMonth, 1).AddMonths(1).AddDays(-1).Day; | ||
var newDay = value.Day > lastDayOfMonth ? lastDayOfMonth : value.Day; | ||
return new DateTime(value.Year, newMonth, newDay, value.Hour, value.Minute, value.Second, value.Millisecond); | ||
} | ||
protected override object? EvaluateYearMonth(YearMonth yearMonth) | ||
{ | ||
var newMonth = Month.Invoke(); | ||
if (newMonth < 1 || newMonth > 12) | ||
return new Null(); | ||
return new YearMonth(yearMonth.Year, newMonth); | ||
} | ||
} |
Oops, something went wrong.