iotgateway/WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Support/DateRange.cs
2021-12-14 14:10:44 +08:00

452 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace WalkingTec.Mvvm.Core
{
public sealed class DateRange
{
private static readonly DateTime UtCDefaultEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static readonly DateTime DefaultEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
private static readonly DateTimeTypeEnum DefaultType = DateTimeTypeEnum.DateTime;
private DateRange() { }
public DateRange(DateTime startTime, DateTime endTime) : this(startTime, endTime, DefaultType, DefaultEpoch) { }
public DateRange(DateTime startTime, DateTime endTime, DateTimeTypeEnum type, DateTime epoch)
{
Type = type;
Epoch = epoch;
SetStartTime(startTime);
SetEndTime(endTime);
}
public DateRange(TimeSpan startSpan, TimeSpan endSpan) : this(startSpan, endSpan, DefaultType, DefaultEpoch) { }
public DateRange(TimeSpan startSpan, TimeSpan endSpan, DateTimeTypeEnum type, DateTime epoch)
{
Type = type;
Epoch = epoch;
SetStartTime(epoch.Add(startSpan));
SetEndTime(epoch.Add(endSpan));
}
public DateRange(DateTimeOffset startOffset, DateTimeOffset endOffset) : this(startOffset, endOffset, DefaultType, DefaultEpoch) { }
public DateRange(DateTimeOffset startOffset, DateTimeOffset endOffset, DateTimeTypeEnum type, DateTime epoch)
{
Type = type;
Epoch = epoch;
SetStartTime(startOffset.DateTime);
SetEndTime(endOffset.DateTime);
}
public readonly DateTime Epoch = DefaultEpoch;
public readonly DateTimeTypeEnum Type = DefaultType;
public string Value => ToString();
private DateTime? _startTime;
public DateTime? GetStartTime()
{
return _startTime;
}
public void SetStartTime(DateTime? value)
{
if (value == null) return;
value = SwitchTime(value.Value);
if (_endTime.HasValue && _endTime.Value < value) return;
_startTime = value;
}
private DateTime? _endTime;
public DateTime? GetEndTime()
{
switch (Type)
{
case DateTimeTypeEnum.Date:
return _endTime?.AddDays(1);
case DateTimeTypeEnum.DateTime when _startTime.HasValue && _endTime.HasValue && _startTime.Value == _endTime.Value:
case DateTimeTypeEnum.DateTime when _endTime.HasValue && _endTime.Value.Hour == 0 && _endTime.Value.Minute == 0 && _endTime.Value.Second == 0 && _endTime.Value.Millisecond == 0:
return _endTime?.AddDays(1);
default:
return _endTime;
}
}
public void SetEndTime(DateTime? value)
{
if (value == null) return;
value = SwitchTime(value.Value);
if (_startTime.HasValue && _startTime.Value > value) return;
_endTime = value;
}
public DateTimeOffset? GetStartOffset()
{
if (_startTime == null)
return null;
return _startTime <= DateTimeOffset.MinValue.LocalDateTime ? DateTimeOffset.MinValue : new DateTimeOffset(GetStartTime().Value);
}
public void SetStartOffset(DateTimeOffset? value)
{
if (value == null) return;
SetStartTime(value.Value.LocalDateTime);
}
public DateTimeOffset? GetEndOffset()
{
if (_endTime == null)
return null;
return _endTime <= DateTimeOffset.MinValue.LocalDateTime ? DateTimeOffset.MinValue : new DateTimeOffset(GetEndTime().Value);
}
public void SetEndOffset(DateTimeOffset? value)
{
if (value == null) return;
SetEndTime(value.Value.LocalDateTime);
}
public TimeSpan? GetStartSpan()
{
if (_endTime == null)
return null;
return GetStartTime() - Epoch.ToLocalTime();
}
public void SetStartSpan(TimeSpan? value)
{
if (value == null) return;
SetStartTime(Epoch.Add(value.Value));
}
public TimeSpan? GetEndSpan()
{
if (_endTime == null)
return null;
return GetEndTime() - Epoch.ToLocalTime();
}
public void SetEndSpan(TimeSpan? value)
{
if (value == null) return;
SetEndTime(Epoch.Add(value.Value));
}
public override string ToString()
{
return ToString(DateTimeFormatDic[Type], "~");
}
public string ToString(string format)
{
return ToString(format, "~");
}
public string ToString(string format, string rangeSplit)
{
if (_startTime.HasValue && _endTime.HasValue)
return $"{_startTime?.ToString(format)} {rangeSplit} {_endTime?.ToString(format)}";
return string.Empty;
}
public static readonly Dictionary<DateTimeTypeEnum, string> DateTimeFormatDic = new Dictionary<DateTimeTypeEnum, string>()
{
{ DateTimeTypeEnum.Date,"yyyy-MM-dd"},
{ DateTimeTypeEnum.DateTime,"yyyy-MM-dd HH:mm:ss"},
{ DateTimeTypeEnum.Year,"yyyy"},
{ DateTimeTypeEnum.Month,"yyyy-MM"},
{ DateTimeTypeEnum.Time,"HH:mm:ss"},
};
private DateTime SwitchTime(DateTime time)
{
if (Epoch.Kind == time.Kind)
return time;
switch (Epoch.Kind)
{
case DateTimeKind.Local:
switch (time.Kind)
{
case DateTimeKind.Unspecified:
return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, time.Millisecond, DateTimeKind.Local);
case DateTimeKind.Utc:
return time.ToLocalTime();
}
break;
case DateTimeKind.Unspecified:
switch (time.Kind)
{
case DateTimeKind.Local:
return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, time.Millisecond, DateTimeKind.Unspecified);
case DateTimeKind.Utc:
return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, time.Millisecond, DateTimeKind.Unspecified);
}
break;
case DateTimeKind.Utc:
switch (time.Kind)
{
case DateTimeKind.Local:
return time.ToUniversalTime();
case DateTimeKind.Unspecified:
return new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, time.Millisecond, DateTimeKind.Utc);
}
break;
}
return time;
}
public static DateRange Default => Today;
public static DateRange NinetyDays
{
get
{
var result = new DateRange(DateTime.Today.AddDays(-90), DateTime.Today);
return result;
}
}
public static DateRange ThirtyDays
{
get
{
var result = new DateRange(DateTime.Today.AddDays(-30), DateTime.Today);
return result;
}
}
public static DateRange TwoWeek
{
get
{
var result = new DateRange(DateTime.Today.AddDays(-14), DateTime.Today);
return result;
}
}
public static DateRange Week
{
get
{
var result = new DateRange(DateTime.Today.AddDays(-7), DateTime.Today);
return result;
}
}
public static DateRange Today
{
get
{
var result = new DateRange(DateTime.Today, DateTime.Today);
return result;
}
}
public static DateRange Yesterday
{
get
{
var result = new DateRange(DateTime.Today.AddDays(-1), DateTime.Today.AddDays(-1));
return result;
}
}
public static DateRange UtcDefault => UtcToday;
public static DateRange UtcNinetyDays
{
get
{
var result = new DateRange(DateTime.UtcNow.Date.AddDays(-90), DateTime.UtcNow.Date);
return result;
}
}
public static DateRange UtcThirtyDays
{
get
{
var result = new DateRange(DateTime.UtcNow.Date.AddDays(-30), DateTime.UtcNow.Date, DefaultType, UtCDefaultEpoch);
return result;
}
}
public static DateRange UtcTwoWeek
{
get
{
var result = new DateRange(DateTime.UtcNow.Date.AddDays(-14), DateTime.UtcNow.Date, DefaultType, UtCDefaultEpoch);
return result;
}
}
public static DateRange UtcWeek
{
get
{
var result = new DateRange(DateTime.UtcNow.Date.AddDays(-7), DateTime.UtcNow.Date, DefaultType, UtCDefaultEpoch);
return result;
}
}
public static DateRange UtcToday
{
get
{
var result = new DateRange(DateTime.UtcNow.Date.AddDays(-1), DateTime.UtcNow.Date, DefaultType, UtCDefaultEpoch);
return result;
}
}
public static DateRange UtcYesterday
{
get
{
var result = new DateRange(DateTime.UtcNow.Date.AddDays(-1), DateTime.UtcNow.Date, DefaultType, UtCDefaultEpoch);
return result;
}
}
private static readonly Dictionary<DateTimeTypeEnum, string> DateTimeRegexDic = new Dictionary<DateTimeTypeEnum, string>()
{
{ DateTimeTypeEnum.DateTime,@"((\d{4}|\d{3}|\d{2}|\d{1})[-](1[0-2]|0?[1-9])[-](3[01]|[12][0-9]|0?[1-9])\s+(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d)"},
{ DateTimeTypeEnum.Date,@"(\d{4}|\d{3}|\d{2}|\d{1})[-](1[0-2]|0?[1-9])[-](3[01]|[12][0-9]|0?[1-9])"},
{ DateTimeTypeEnum.Month,@"(\d{4}|\d{3}|\d{2}|\d{1})[-](1[0-2]|0?[1-9])"},
{ DateTimeTypeEnum.Time,@"(20|21|22|23|[0-1]\d):[0-5]\d:[0-5]\d"},
{ DateTimeTypeEnum.Year,@"(\d{4}|\d{3}|\d{2}|\d{1})"},
};
public static bool TryParse(string input, out DateRange result)
{
if (TryParse(input, new[] { '~' }, out result)) return true;
result = null;
foreach (var pair in DateTimeRegexDic)
{
if (Regex.IsMatch(input, pair.Value))
{
var values = Regex.Matches(input, pair.Value, RegexOptions.IgnorePatternWhitespace);
return values.Count == 2 && TryParse(values[0].Value, values[1].Value, DefaultEpoch, out result);
}
}
return false;
}
public static bool TryParse(string input, char[] separator, out DateRange result)
{
result = null;
if (string.IsNullOrEmpty(input))
{
return false;
}
var values = input.Split(separator, StringSplitOptions.RemoveEmptyEntries);
return values.Length == 2 && TryParse(values[0], values[1], DefaultEpoch, out result);
}
public static bool TryParse(string input, string[] separator, out DateRange result)
{
result = null;
if (string.IsNullOrEmpty(input))
{
return false;
}
var values = input.Split(separator, StringSplitOptions.RemoveEmptyEntries);
return values.Length == 2 && TryParse(values[0], values[1], DefaultEpoch, out result);
}
public static bool TryParse(string[] input, out DateRange result)
{
result = null;
return input.Length == 2 && TryParse(input[0], input[1], DefaultEpoch, out result);
}
public static bool TryParse(string startTime, string endTime, DateTime epoch, out DateRange result)
{
result = null;
switch (startTime.Trim().Length)
{
//Year
case 4:
{
if (!int.TryParse(startTime, out var y1)) return false;
if (y1 < 1 || y1 > 9999) return false;
if (!int.TryParse(endTime, out var y2)) return false;
if (y2 < 1 || y2 > 9999) return false;
result = new DateRange(new DateTime(y1, 1, 1, 0, 0, 0, epoch.Kind), new DateTime(y2, 1, 1, 0, 0, 0, epoch.Kind));
return true;
}
//Month
case 7:
{
if (!DateTime.TryParse(startTime, out var v1)) return false;
if (!DateTime.TryParse(endTime, out var v2)) return false;
result = new DateRange(v1, v2, DateTimeTypeEnum.Month, epoch);
return true;
}
//Time
case 8:
{
if (!DateTime.TryParse(startTime, out var v1)) return false;
if (!DateTime.TryParse(endTime, out var v2)) return false;
result = new DateRange(v1, v2, DateTimeTypeEnum.Time, epoch);
return true;
}
//Date
case 10:
{
if (!DateTime.TryParse(startTime, out var v1)) return false;
if (!DateTime.TryParse(endTime, out var v2)) return false;
result = new DateRange(v1, v2, DateTimeTypeEnum.Date, epoch);
return true;
}
//DateTime
default:
{
if (!DateTime.TryParse(startTime, out var v1)) return false;
if (!DateTime.TryParse(endTime, out var v2)) return false;
result = new DateRange(v1, v2, DateTimeTypeEnum.DateTime, epoch);
return true;
}
}
}
}
}