|
@@ -0,0 +1,278 @@
|
|
|
+using System;
|
|
|
+using System.Collections.Generic;
|
|
|
+using System.Linq;
|
|
|
+using System.Text;
|
|
|
+using System.Threading.Tasks;
|
|
|
+
|
|
|
+namespace TCCElectricityTimes
|
|
|
+{
|
|
|
+ internal class ElectricityTimes
|
|
|
+ {
|
|
|
+ #region Fields
|
|
|
+ // 西曆假日,每年固定5天
|
|
|
+ // 開國紀念日, 和平紀念日, 兒童節, 勞動節, 國慶日
|
|
|
+ private List<string> gregorianCalendarHoliday = new List<string>()
|
|
|
+ {
|
|
|
+ "0101", "0228", "0404", "0501", "1010"
|
|
|
+ };
|
|
|
+
|
|
|
+ // 農曆假日(+民族掃墓節)對應的西曆日期,每年9天(當清明節氣為4/4時和兒童節同天),注意農曆可能有閏月
|
|
|
+ // 農曆除夕, 初一至初五, 民族掃墓節, 端午節, 中秋節
|
|
|
+ private List<string> lunarCalendarHoliday = new List<string>()
|
|
|
+ {
|
|
|
+ "20220131", "20220201", "20220202", "20220203", "20220204", "20220205", "20220405", "20220603", "20220910",
|
|
|
+ "20230121", "20230122", "20230123", "20230124", "20230125", "20230126", "20230405", "20230622", "20230929",
|
|
|
+ "20240209", "20240210", "20240211", "20240212", "20240213", "20240214", "20240404", "20240610", "20240917",
|
|
|
+ "20250128", "20250129", "20250130", "20250131", "20250201", "20250202", "20250404", "20250531", "20251006",
|
|
|
+ "20260216", "20260217", "20260218", "20260219", "20260220", "20260221", "20260405", "20260619", "20260925",
|
|
|
+ "20270205", "20270206", "20270207", "20270208", "20270209", "20270210", "20270405", "20270609", "20270915",
|
|
|
+ "20280125", "20280126", "20280127", "20280128", "20280129", "20280130", "20280404", "20280528", "20281003",
|
|
|
+ "20290212", "20290213", "20290214", "20290215", "20290216", "20290217", "20290404", "20290616", "20290922",
|
|
|
+ "20300202", "20300203", "20300204", "20300205", "20300206", "20300207", "20300405", "20300605", "20300912",
|
|
|
+ "20310122", "20310123", "20310124", "20310125", "20310126", "20310127", "20310405", "20310624", "20311001",
|
|
|
+ "20320210", "20320211", "20320212", "20320213", "20320214", "20320215", "20320404", "20320612", "20320919",
|
|
|
+ "20330130", "20330131", "20330201", "20330202", "20330203", "20330204", "20330404", "20330601", "20330908",
|
|
|
+ "20340218", "20340219", "20340220", "20340221", "20340222", "20340223", "20340405", "20340620", "20340927",
|
|
|
+ "20350207", "20350208", "20350209", "20350210", "20350211", "20350212", "20350405", "20350610", "20350916",
|
|
|
+ "20360127", "20360128", "20360129", "20360130", "20360131", "20360201", "20360404", "20360530", "20361004",
|
|
|
+ "20370214", "20370215", "20370216", "20370217", "20370218", "20370219", "20370404", "20370618", "20370924",
|
|
|
+ "20380203", "20380204", "20380205", "20380206", "20380207", "20380208", "20380405", "20380607", "20380913",
|
|
|
+ "20390123", "20390124", "20390125", "20390126", "20390127", "20390128", "20390405", "20390527", "20391002",
|
|
|
+ "20400211", "20400212", "20400213", "20400214", "20400215", "20400216", "20400404", "20400614", "20400920",
|
|
|
+ "20410131", "20410201", "20410202", "20410203", "20410204", "20410205", "20410404", "20410603", "20410910",
|
|
|
+ "20420121", "20420122", "20420123", "20420124", "20420125", "20420126", "20420404", "20420622", "20420928",
|
|
|
+ "20430209", "20430210", "20430211", "20430212", "20430213", "20430214", "20430405", "20430611", "20430917",
|
|
|
+ "20440129", "20440130", "20440131", "20440201", "20440202", "20440203", "20440404", "20440531", "20441005",
|
|
|
+ "20450216", "20450217", "20450218", "20450219", "20450220", "20450221", "20450404", "20450619", "20450925",
|
|
|
+ "20460205", "20460206", "20460207", "20460208", "20460209", "20460210", "20460404", "20460608", "20460915",
|
|
|
+ "20470125", "20470126", "20470127", "20470128", "20470129", "20470130", "20470405", "20470529", "20471004",
|
|
|
+ "20480213", "20480214", "20480215", "20480216", "20480217", "20480218", "20480404", "20480615", "20480922",
|
|
|
+ "20490201", "20490202", "20490203", "20490204", "20490205", "20490206", "20490404", "20490604", "20490911",
|
|
|
+ "20500122", "20500123", "20500124", "20500125", "20500126", "20500127", "20500404", "20500623", "20500930",
|
|
|
+ "20510210", "20510211", "20510212", "20510213", "20510214", "20510215", "20510405", "20510613", "20510919",
|
|
|
+ "20520131", "20520201", "20520202", "20520203", "20520204", "20520205", "20520404", "20520601", "20520907",
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ private List<TaiPowerDailyPeriod> holidayTimesList = new List<TaiPowerDailyPeriod>();
|
|
|
+ private List<TaiPowerDailyPeriod> saturdayTimesList = new List<TaiPowerDailyPeriod>();
|
|
|
+ private List<TaiPowerDailyPeriod> nsworkdayTimesList = new List<TaiPowerDailyPeriod>();
|
|
|
+ private List<TaiPowerDailyPeriod> suworkdayTimesList = new List<TaiPowerDailyPeriod>();
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region Constructors
|
|
|
+ public ElectricityTimes()
|
|
|
+ {
|
|
|
+ GenerateElectricityTimesList();
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region Instance Methods
|
|
|
+ /// <summary>
|
|
|
+ /// 決定所輸入時間段主要歸屬的用電時段種類
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="beginDateTime">起始日期時間</param>
|
|
|
+ /// <param name="endDateTime">截止日期時間</param>
|
|
|
+ /// <returns>用電時段種類(尖峰、半尖峰、離峰)</returns>
|
|
|
+ public ElectricityTimesType DetermineElectricityTimesType(DateTime beginDateTime, DateTime endDateTime)
|
|
|
+ {
|
|
|
+ ElectricityTimesType eTimesType = ElectricityTimesType.Undefine;
|
|
|
+ DailyType daytype;
|
|
|
+ DateTime dt;
|
|
|
+ double[] typeHours = new double[3];
|
|
|
+ double beginHour;
|
|
|
+ double endHour;
|
|
|
+
|
|
|
+ if (beginDateTime.Date == endDateTime.Date) // not overnight
|
|
|
+ {
|
|
|
+ daytype = DetermineDayType(beginDateTime);
|
|
|
+
|
|
|
+ dt = new DateTime(beginDateTime.Year, beginDateTime.Month, beginDateTime.Day);
|
|
|
+ beginHour = (beginDateTime - dt).TotalHours;
|
|
|
+ endHour = (endDateTime - dt).TotalHours;
|
|
|
+
|
|
|
+ typeHours = CalculateElectricityTimesType(beginHour, endHour, daytype);
|
|
|
+ }
|
|
|
+ else if (beginDateTime.Date < endDateTime.Date) // overnight
|
|
|
+ {
|
|
|
+ double[] typeHoursFirst = new double[3];
|
|
|
+ double[] typeHoursSecond = new double[3];
|
|
|
+
|
|
|
+ dt = new DateTime(beginDateTime.Year, beginDateTime.Month, beginDateTime.Day);
|
|
|
+ beginHour = (beginDateTime - dt).TotalHours;
|
|
|
+ daytype = DetermineDayType(beginDateTime);
|
|
|
+ typeHoursFirst = CalculateElectricityTimesType(beginHour, 24.0, daytype);
|
|
|
+
|
|
|
+ dt = new DateTime(endDateTime.Year, endDateTime.Month, endDateTime.Day);
|
|
|
+ endHour = (endDateTime - dt).TotalHours;
|
|
|
+ daytype = DetermineDayType(endDateTime);
|
|
|
+ typeHoursSecond = CalculateElectricityTimesType(0.0, endHour, daytype);
|
|
|
+
|
|
|
+ for (int i = 0; i < 3; i++)
|
|
|
+ {
|
|
|
+ typeHours[i] = typeHoursFirst[i] + typeHoursSecond[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ; // something wrong
|
|
|
+ }
|
|
|
+
|
|
|
+ int mainIdx = Array.IndexOf(typeHours, typeHours.Max());
|
|
|
+
|
|
|
+ return (ElectricityTimesType)mainIdx;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void GenerateElectricityTimesList()
|
|
|
+ {
|
|
|
+ holidayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 0.0, PeriodEnd = 24.0 });
|
|
|
+
|
|
|
+ saturdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 0.0, PeriodEnd = 7.5 });
|
|
|
+ saturdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.SemiPeak, PeriodBegin = 7.5, PeriodEnd = 22.5 });
|
|
|
+ saturdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 22.5, PeriodEnd = 24.0 });
|
|
|
+
|
|
|
+ nsworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 0.0, PeriodEnd = 7.5 });
|
|
|
+ nsworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.SemiPeak, PeriodBegin = 7.5, PeriodEnd = 22.5 });
|
|
|
+ nsworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 22.5, PeriodEnd = 24.0 });
|
|
|
+
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 0.0, PeriodEnd = 7.5 });
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.SemiPeak, PeriodBegin = 7.5, PeriodEnd = 13.0 });
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.Peak, PeriodBegin = 13.0, PeriodEnd = 17.0 });
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.SemiPeak, PeriodBegin = 17.0, PeriodEnd = 18.0 });
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.Peak, PeriodBegin = 18.0, PeriodEnd = 20.0 });
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.SemiPeak, PeriodBegin = 20.0, PeriodEnd = 22.5 });
|
|
|
+ suworkdayTimesList.Add(new TaiPowerDailyPeriod() { Type = ElectricityTimesType.OffPeak, PeriodBegin = 22.5, PeriodEnd = 24.0 });
|
|
|
+ }
|
|
|
+
|
|
|
+ private DailyType DetermineDayType(DateTime datetime)
|
|
|
+ {
|
|
|
+ DailyType dayType = DailyType.Unknown;
|
|
|
+ string ymdDate = datetime.ToString("yyyyMMdd");
|
|
|
+ int mdDate = Int32.Parse(ymdDate.Substring(4, 4));
|
|
|
+
|
|
|
+ dayType = (datetime.DayOfWeek == DayOfWeek.Sunday) ? DailyType.Holiday : dayType;
|
|
|
+ dayType = (datetime.DayOfWeek == DayOfWeek.Saturday) ? DailyType.Saturday : dayType;
|
|
|
+ dayType = gregorianCalendarHoliday.Where(t => t == ymdDate.Substring(4, 4)).FirstOrDefault() != null ? DailyType.Holiday : dayType;
|
|
|
+ dayType = lunarCalendarHoliday.Where(t => t == ymdDate).FirstOrDefault() != null ? DailyType.Holiday : dayType;
|
|
|
+ if (dayType == DailyType.Unknown)
|
|
|
+ {
|
|
|
+ dayType = (mdDate < 601 || mdDate > 930) ? DailyType.NonSummerWorkDay : DailyType.SummerWorkDay;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dayType;
|
|
|
+ }
|
|
|
+
|
|
|
+ private double[] CalculateElectricityTimesType(double beginHour, double endHour, DailyType dayType)
|
|
|
+ {
|
|
|
+ List<TaiPowerDailyPeriod> periodList = new List<TaiPowerDailyPeriod>();
|
|
|
+
|
|
|
+ switch (dayType)
|
|
|
+ {
|
|
|
+ case DailyType.Holiday:
|
|
|
+ periodList = new List<TaiPowerDailyPeriod>(holidayTimesList);
|
|
|
+ break;
|
|
|
+ case DailyType.Saturday:
|
|
|
+ periodList = new List<TaiPowerDailyPeriod>(saturdayTimesList);
|
|
|
+ break;
|
|
|
+ case DailyType.NonSummerWorkDay:
|
|
|
+ periodList = new List<TaiPowerDailyPeriod>(nsworkdayTimesList);
|
|
|
+ break;
|
|
|
+ case DailyType.SummerWorkDay:
|
|
|
+ periodList = new List<TaiPowerDailyPeriod>(suworkdayTimesList);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ int beginIdx = -1;
|
|
|
+ int endIdx = -1;
|
|
|
+ for (int i = periodList.Count - 1; i >= 0; i--)
|
|
|
+ {
|
|
|
+ if (beginHour >= periodList[i].PeriodBegin)
|
|
|
+ {
|
|
|
+ beginIdx = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (int i = 0; i < periodList.Count; i++)
|
|
|
+ {
|
|
|
+ if (endHour <= periodList[i].PeriodEnd)
|
|
|
+ {
|
|
|
+ endIdx = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ double[] periodHours = new double[periodList.Count];
|
|
|
+ for (int i = beginIdx; i <= endIdx; i++)
|
|
|
+ {
|
|
|
+ if (beginIdx == endIdx)
|
|
|
+ {
|
|
|
+ periodHours[i] = endHour - beginHour;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == beginIdx)
|
|
|
+ {
|
|
|
+ periodHours[i] = periodList[i].PeriodEnd - beginHour;
|
|
|
+ }
|
|
|
+ else if (i == endIdx)
|
|
|
+ {
|
|
|
+ periodHours[i] = endHour - periodList[i].PeriodBegin;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ periodHours[i] = periodList[i].PeriodEnd - periodList[i].PeriodBegin;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ double[] typeHours = new double[3]; // 0:Peak; 1:SemiPeak; 2:OffPeak
|
|
|
+ for (int i = 0; i < periodList.Count; i++)
|
|
|
+ {
|
|
|
+ switch (periodList[i].Type)
|
|
|
+ {
|
|
|
+ case ElectricityTimesType.Peak:
|
|
|
+ typeHours[0] += periodHours[i];
|
|
|
+ break;
|
|
|
+ case ElectricityTimesType.SemiPeak:
|
|
|
+ typeHours[1] += periodHours[i];
|
|
|
+ break;
|
|
|
+ case ElectricityTimesType.OffPeak:
|
|
|
+ typeHours[2] += periodHours[i];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //int mainIdx = Array.IndexOf(type, type.Max());
|
|
|
+
|
|
|
+ return typeHours;
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+
|
|
|
+ #region Nested Enums and Classes
|
|
|
+ public enum DailyType
|
|
|
+ {
|
|
|
+ Holiday = 0,
|
|
|
+ Saturday,
|
|
|
+ NonSummerWorkDay,
|
|
|
+ SummerWorkDay,
|
|
|
+ Unknown
|
|
|
+ }
|
|
|
+
|
|
|
+ public enum ElectricityTimesType
|
|
|
+ {
|
|
|
+ Peak = 0,
|
|
|
+ SemiPeak,
|
|
|
+ OffPeak,
|
|
|
+ Undefine
|
|
|
+ }
|
|
|
+
|
|
|
+ public class TaiPowerDailyPeriod
|
|
|
+ {
|
|
|
+ public ElectricityTimesType Type { get; set; }
|
|
|
+ public double PeriodBegin { get; set; }
|
|
|
+ public double PeriodEnd { get; set; }
|
|
|
+ }
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|