// 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());
}
}
}
}