// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data; namespace Spludlow { /// /// Put dates into periods of different sizes /// public class Periods { public enum PeriodSize { Minute, // N Hour, Day, Week, Month, Quarter, Year }; public static DateTime[] Range(PeriodSize periodSize, DateTime firstDate, DateTime lastDate) { firstDate = RoundDown(periodSize, firstDate); lastDate = RoundDown(periodSize, lastDate); List range = new List(); for (DateTime dateTime = firstDate; dateTime <= lastDate; dateTime = AddPeriod(periodSize, dateTime)) range.Add(dateTime); return range.ToArray(); } public static string PeriodName(PeriodSize periodSize, DateTime date) { return PeriodNameRaw(periodSize, RoundDown(periodSize, date)); } /// /// Date must already be rounded /// public static string PeriodNameRaw(PeriodSize periodSize, DateTime date) { StringBuilder text = new StringBuilder(); switch (periodSize) { case PeriodSize.Minute: text.Append("N"); text.Append(date.ToString("mm-HH-dd")); break; case PeriodSize.Hour: text.Append("H"); text.Append(date.ToString("HH-dd")); break; case PeriodSize.Day: text.Append("D"); text.Append(date.ToString("dd-MM-yyyy")); break; case PeriodSize.Week: date = RoundToMonday(date); text.Append("W"); text.Append(date.ToString("dd-MM-yyyy")); break; case PeriodSize.Month: text.Append("M"); text.Append(date.ToString("MM-yyyy")); break; case PeriodSize.Quarter: text.Append("Q"); int quarter = ((date.Month - 1) / 3) + 1; text.Append(quarter.ToString()); text.Append("-"); text.Append(date.ToString("yyyy")); break; case PeriodSize.Year: text.Append("Y"); text.Append(date.ToString("yyyy")); break; default: throw new ApplicationException("PeriodSize not supported: " + periodSize.ToString()); } return text.ToString(); } public static DateTime RoundDown(PeriodSize periodSize, DateTime dateTime) { switch (periodSize) { case PeriodSize.Minute: return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0); case PeriodSize.Hour: return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, 0, 0); case PeriodSize.Day: return dateTime.Date; case PeriodSize.Week: return RoundToMonday(dateTime.Date); case PeriodSize.Month: return new DateTime(dateTime.Year, dateTime.Month, 1); case PeriodSize.Quarter: return RoundToQuarter(dateTime); case PeriodSize.Year: return new DateTime(dateTime.Year, 1, 1); default: throw new ApplicationException("PeriodSize not supported: " + periodSize.ToString()); } } private static DateTime RoundToMonday(DateTime date) { date = date.Date; while (date.DayOfWeek != DayOfWeek.Monday) date = date.AddDays(-1); return date; } private static DateTime RoundToQuarter(DateTime date) { //01 / 01 2 3 //01 / 04 5 6 //01 / 07 8 9 //01 / 10 11 12 date = new DateTime(date.Year, date.Month, 1); while ((date.Month % 3) != 1) date = date.AddMonths(-1); return date; } private static DateTime AddPeriod(PeriodSize periodSize, DateTime dateTime) // must already be rounded { switch (periodSize) // "yyyy-MM-dd-HH-mm-ss-fff" { case PeriodSize.Minute: return dateTime.AddMinutes(1); case PeriodSize.Hour: return dateTime.AddHours(1); case PeriodSize.Day: return dateTime.AddDays(1); case PeriodSize.Week: return dateTime.AddDays(7); case PeriodSize.Month: return dateTime.AddMonths(1); case PeriodSize.Quarter: return dateTime.AddMonths(3); case PeriodSize.Year: return dateTime.AddYears(1); default: throw new ApplicationException("PeriodSize not supported: " + periodSize.ToString()); } } } }