Skip to content

Instantly share code, notes, and snippets.

@PatrickRainer
Created October 3, 2023 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PatrickRainer/f7f0b02626c5423d51bf57f1d0242e8f to your computer and use it in GitHub Desktop.
Save PatrickRainer/f7f0b02626c5423d51bf57f1d0242e8f to your computer and use it in GitHub Desktop.
A class for using YearMonth DataType
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