209 lines
6.8 KiB (Stored with Git LFS)
C#
209 lines
6.8 KiB (Stored with Git LFS)
C#
using System;
|
|
using Superlazy;
|
|
|
|
public static class SLDateTimeUtil
|
|
{
|
|
private const double oADateMaxAsDouble = 2958466.0;
|
|
private const double oADateMinAsDouble = -657435.0;
|
|
private const int millisPerSecond = 1000;
|
|
private const int millisPerMinute = millisPerSecond * 60;
|
|
private const int millisPerHour = millisPerMinute * 60;
|
|
private const int millisPerDay = millisPerHour * 24;
|
|
|
|
// Number of 100ns ticks per time unit
|
|
private const long ticksPerMillisecond = 10000;
|
|
|
|
private const long ticksPerSecond = ticksPerMillisecond * 1000;
|
|
private const long ticksPerMinute = ticksPerSecond * 60;
|
|
private const long ticksPerHour = ticksPerMinute * 60;
|
|
private const long ticksPerDay = ticksPerHour * 24;
|
|
|
|
// Number of days in a non-leap year
|
|
private const int daysPerYear = 365;
|
|
|
|
// Number of days in 4 years
|
|
private const int daysPer4Years = daysPerYear * 4 + 1; // 1461
|
|
|
|
// Number of days in 100 years
|
|
private const int daysPer100Years = daysPer4Years * 25 - 1; // 36524
|
|
|
|
// Number of days in 400 years
|
|
private const int daysPer400Years = daysPer100Years * 4 + 1; // 146097
|
|
|
|
// Number of days from 1/1/0001 to 12/31/1600
|
|
|
|
// Number of days from 1/1/0001 to 12/30/1899
|
|
private const int daysTo1899 = daysPer400Years * 4 + daysPer100Years * 3 - 367;
|
|
|
|
// Number of days from 1/1/0001 to 12/31/1969
|
|
|
|
// Number of days from 1/1/0001 to 12/31/9999
|
|
private const int daysTo10000 = daysPer400Years * 25 - 366; // 3652059
|
|
|
|
private const long doubleDateOffset = daysTo1899 * ticksPerDay;
|
|
private const long maxMillis = (long)daysTo10000 * millisPerDay;
|
|
|
|
private const long oADateMinAsTicks = (daysPer100Years - daysPerYear) * ticksPerDay;
|
|
|
|
private static long DoubleDateToTicks(double value)
|
|
{
|
|
// The check done this way will take care of NaN
|
|
if (!(value < oADateMaxAsDouble) || !(value > oADateMinAsDouble))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Conversion to long will not cause an overflow here, as at this point the "value" is in between OADateMinAsDouble and OADateMaxAsDouble
|
|
var millis = (long)(value * millisPerDay + (value >= 0 ? 0.5 : -0.5));
|
|
// The interesting thing here is when you have a value like 12.5 it all positive 12 days and 12 hours from 01/01/1899
|
|
// However if you a value of -12.25 it is minus 12 days but still positive 6 hours, almost as though you meant -11.75 all negative
|
|
// This line below fixes up the millis in the negative case
|
|
if (millis < 0)
|
|
{
|
|
millis -= (millis % millisPerDay) * 2;
|
|
}
|
|
|
|
millis += doubleDateOffset / ticksPerMillisecond;
|
|
|
|
if (millis < 0 || millis >= maxMillis)
|
|
{
|
|
return 0;
|
|
}
|
|
return millis * ticksPerMillisecond;
|
|
}
|
|
|
|
private static double TicksToOADate(long value)
|
|
{
|
|
if (value == 0)
|
|
return 0.0; // Returns OleAut's zero'ed date value.
|
|
if (value < ticksPerDay) // This is a fix for VB. They want the default day to be 1/1/0001 rathar then 12/30/1899.
|
|
value += doubleDateOffset; // We could have moved this fix down but we would like to keep the bounds check.
|
|
if (value < oADateMinAsTicks)
|
|
throw new OverflowException();
|
|
// Currently, our max date == OA's max date (12/31/9999), so we don't
|
|
// need an overflow check in that direction.
|
|
var millis = (value - doubleDateOffset) / ticksPerMillisecond;
|
|
if (millis < 0)
|
|
{
|
|
var frac = millis % millisPerDay;
|
|
if (frac != 0) millis -= (millisPerDay + frac) * 2;
|
|
}
|
|
return Math.Round((double)millis / millisPerDay, 10);
|
|
}
|
|
|
|
public static DateTime FromSLDate(double d)
|
|
{
|
|
return new DateTime(DoubleDateToTicks(d), DateTimeKind.Unspecified);
|
|
}
|
|
|
|
public static DateTime FromSLDateToKRDate(double d)
|
|
{
|
|
return (new DateTime(DoubleDateToTicks(d), DateTimeKind.Unspecified)).AddHours(9);
|
|
}
|
|
|
|
public static DateTime ToDateTime(this SLEntity value)
|
|
{
|
|
return new DateTime(DoubleDateToTicks(value), DateTimeKind.Unspecified);
|
|
}
|
|
|
|
public static DateTime ToLocalDateTime(this SLEntity value)
|
|
{
|
|
return new DateTime(DoubleDateToTicks(value), DateTimeKind.Unspecified).ToLocalTime();
|
|
}
|
|
|
|
public static DateTime ToDayStart(this DateTime dt)
|
|
{
|
|
return new DateTime(dt.Year, dt.Month, dt.Day);
|
|
}
|
|
|
|
public static DateTime ToKRInitTime(this DateTime dt)
|
|
{
|
|
return dt.AddDays(1).AddHours(3).ToDayStart().AddHours(-3);
|
|
}
|
|
|
|
public static DateTime ToRankingEndTime(this DateTime dt)
|
|
{
|
|
return dt.AddDays(1).AddHours(3).AddMinutes(15).ToDayStart().AddHours(-3).AddMinutes(-15);
|
|
}
|
|
|
|
public static DateTime ToWeekliyInitTime(this DateTime dt)
|
|
{
|
|
if (dt < dt.ToKRInitTime().AddDays(-1))
|
|
{
|
|
return dt.ToKRInitTime().AddDays(-1);
|
|
}
|
|
else
|
|
{
|
|
var delta = 7 + DayOfWeek.Monday - dt.DayOfWeek;
|
|
return dt.AddDays(delta).AddHours(3).ToDayStart().AddHours(-3);
|
|
}
|
|
}
|
|
|
|
public static double ToSLDate(this DateTime dt)
|
|
{
|
|
return TicksToOADate(dt.Ticks);
|
|
}
|
|
|
|
public static double FromKRDateToSLDate(this DateTime dt)
|
|
{
|
|
return TicksToOADate(dt.AddHours(-9).Ticks);
|
|
}
|
|
|
|
public static string ToSLDateString(this DateTime dt)
|
|
{
|
|
return dt.ToString("yyyy-MM-dd");
|
|
}
|
|
|
|
public static string ToSLDateTimeString(this DateTime dt)
|
|
{
|
|
return dt.ToString("yyyy-MM-dd HH:mm:ss");
|
|
}
|
|
|
|
public static string ToSLDateTimeString(this DateTimeOffset dt)
|
|
{
|
|
return dt.ToString("yyyy-MM-dd HH:mm:ss");
|
|
}
|
|
|
|
public static bool IsDateIn(DateTime date, SLEntity checkDate)
|
|
{
|
|
var start = new DateTime(checkDate["YStart"], checkDate["MStart"], checkDate["DStart"], checkDate["HStart"], 0, 0);
|
|
|
|
if (checkDate["YEnd"] == false) checkDate["YEnd"] = checkDate["YStart"];
|
|
if (checkDate["MEnd"] == false) checkDate["MEnd"] = checkDate["MStart"];
|
|
if (checkDate["DEnd"] == false) checkDate["DEnd"] = checkDate["DStart"];
|
|
if (checkDate["HEnd"] == false) checkDate["HEnd"] = checkDate["HStart"];
|
|
|
|
var end = new DateTime(checkDate["YEnd"], checkDate["MEnd"], checkDate["DEnd"], checkDate["HEnd"], 0, 0);
|
|
return date >= start && date < end;
|
|
}
|
|
}
|
|
|
|
public abstract class SLDateTime
|
|
{
|
|
private static SLDateTime instance;
|
|
|
|
public static void Init(SLDateTime inst)
|
|
{
|
|
instance = inst;
|
|
}
|
|
|
|
public static DateTime Now
|
|
{
|
|
get
|
|
{
|
|
if (instance == null) return DateTime.UtcNow;
|
|
|
|
return instance.GetNow();
|
|
}
|
|
set
|
|
{
|
|
if (instance == null) return;
|
|
|
|
instance.SetNow(value);
|
|
}
|
|
}
|
|
|
|
protected abstract DateTime GetNow();
|
|
|
|
protected abstract void SetNow(DateTime now);
|
|
} |