Created
October 3, 2023 08:45
-
-
Save PatrickRainer/f7f0b02626c5423d51bf57f1d0242e8f to your computer and use it in GitHub Desktop.
A class for using YearMonth DataType
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
using System.Collections.ObjectModel; | |
/// <summary> | |
/// Represents a year and a month | |
/// </summary> | |
public struct YearMonth : IComparable<YearMonth> | |
{ | |
public YearMonth(int year, int month) | |
{ | |
if (year < 1900 || year > 9999) | |
throw new ArgumentException("Year must be between 1900 and 9999", nameof(year)); | |
if (month < 1 || month > 12) | |
throw new ArgumentException("Month must be between 1 and 12", nameof(month)); | |
Year = year; | |
Month = month; | |
} | |
bool Equals(YearMonth other) | |
{ | |
return Year == other.Year && Month == other.Month; | |
} | |
public override bool Equals(object? obj) | |
{ | |
return obj is YearMonth other && Equals(other); | |
} | |
public override int GetHashCode() | |
{ | |
return HashCode.Combine(Year, Month); | |
} | |
public int Year { get; private init; } | |
public int Month { get; private init; } | |
/// <summary> | |
/// Creates a YearMonth from a DateTime | |
/// </summary> | |
/// <param name="date"></param> | |
/// <returns></returns> | |
public static YearMonth FromDateTime(DateTime date) | |
{ | |
return new YearMonth { Year = date.Year, Month = date.Month }; | |
} | |
/// <summary> | |
/// Creates a YearMonth from a SAP period string | |
/// Format: YYYYMM | |
/// </summary> | |
/// <param name="sapPeriodString"></param> | |
/// <returns></returns> | |
public static YearMonth FromSapPeriodString(string sapPeriodString) | |
{ | |
// Validate string | |
if (sapPeriodString.Length != 6) | |
throw new ArgumentException("SAP period string must be 6 characters long.", nameof(sapPeriodString)); | |
var year = int.Parse(sapPeriodString.Substring(0, 4)); | |
var month = int.Parse(sapPeriodString.Substring(4, 2)); | |
return new YearMonth { Year = year, Month = month }; | |
} | |
/// <summary> | |
/// Creates a Distinct List of YearMonth from a List of DateTime | |
/// </summary> | |
/// <param name="dateTimes"></param> | |
/// <returns></returns> | |
public static List<YearMonth> CreateDistinctPeriodsFromDates(IEnumerable<DateTime> dateTimes) | |
{ | |
var result = new Collection<YearMonth>(); | |
foreach (var dateTime in dateTimes) result.Add(new YearMonth(dateTime.Year, dateTime.Month)); | |
// Distinct result and sort by year and month | |
return result.Distinct().OrderBy(x => x.Year).ThenBy(x => x.Month).ToList(); | |
} | |
/// <summary> | |
/// ToString override in the format YYYY - MM | |
/// </summary> | |
/// <returns></returns> | |
public override string ToString() | |
{ | |
return $"{Year}-{Month.ToString("00")}"; | |
} | |
public int CompareTo(YearMonth compareToObj) | |
{ | |
if (ToInt() < compareToObj.ToInt()) return -1; | |
if (ToInt() > compareToObj.ToInt()) return 1; | |
return 0; | |
} | |
/// <summary> | |
/// Creates a List of the last 12 periods from now including the current month | |
/// </summary> | |
/// <returns></returns> | |
public static List<YearMonth> CreateLast12Periods() | |
{ | |
var result = new List<YearMonth>(); | |
var now = DateTime.Now; | |
result.Add(new YearMonth(now.Year, now.Month)); | |
for (var i = 1; i < 12; i++) | |
{ | |
var subtractedMonth = now.AddMonths(-i); | |
result.Add(new YearMonth(subtractedMonth.Year, subtractedMonth.Month)); | |
} | |
return result.OrderBy(x => x.Year).ThenBy(x => x.Month).ToList(); | |
} | |
public string? ToSapPeriodString() | |
{ | |
return Year + Month.ToString("00"); | |
} | |
int ToInt() | |
{ | |
var yearMonthCombinedString = Year + Month.ToString("00"); | |
return int.Parse(yearMonthCombinedString); | |
} | |
public YearMonth NextMonth() | |
{ | |
if (Month == 12) | |
return new YearMonth(Year + 1, 1); | |
return new YearMonth(Year, Month + 1); | |
} | |
public YearMonth PreviousMonth() | |
{ | |
if (Month == 1) | |
return new YearMonth(Year - 1, 12); | |
return new YearMonth(Year, Month - 1); | |
} | |
public static bool operator ==(YearMonth left, YearMonth right) | |
{ | |
return left.Equals(right); | |
} | |
public static bool operator !=(YearMonth left, YearMonth right) | |
{ | |
return !left.Equals(right); | |
} | |
public static bool operator <(YearMonth left, YearMonth right) | |
{ | |
return left.CompareTo(right) < 0; | |
} | |
public static bool operator >(YearMonth left, YearMonth right) | |
{ | |
return left.CompareTo(right) > 0; | |
} | |
public static bool operator <=(YearMonth left, YearMonth right) | |
{ | |
var result = left.CompareTo(right) <= 0; | |
return result; | |
} | |
public static bool operator >=(YearMonth left, YearMonth right) | |
{ | |
return left.CompareTo(right) >= 0; | |
} | |
public YearMonth SubtractMonths(int months) | |
{ | |
var result = new YearMonth(Year, Month); | |
for (var i = 0; i < months; i++) result = result.PreviousMonth(); | |
return result; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment