|
|
@ -11,7 +11,7 @@ namespace Apewer |
|
|
|
public static class ClockUtility |
|
|
|
{ |
|
|
|
|
|
|
|
#region DateTime
|
|
|
|
#region To DateTime
|
|
|
|
|
|
|
|
/// <summary>尝试转换内容为 DateTime 实例。</summary>
|
|
|
|
public static Class<DateTime> DateTime(object value) |
|
|
@ -22,8 +22,7 @@ namespace Apewer |
|
|
|
try |
|
|
|
{ |
|
|
|
var text = value.ToString(); |
|
|
|
var parsed = System.DateTime.TryParse(text, out var result); |
|
|
|
return parsed ? new Class<DateTime>(result) : null; |
|
|
|
return Parse(text); |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
@ -31,6 +30,27 @@ namespace Apewer |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>尝试转换内容为 DateTime 实例。</summary>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
public static DateTime DateTime(object value, Func<DateTime> failed) |
|
|
|
{ |
|
|
|
if (failed == null) throw new ArgumentNullException(nameof(failed)); |
|
|
|
|
|
|
|
var parsed = DateTime(value); |
|
|
|
if (parsed != null) return parsed.Value; |
|
|
|
|
|
|
|
return failed.Invoke(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>尝试转换内容为 DateTime 实例。</summary>
|
|
|
|
public static DateTime DateTime(object value, DateTime failed) |
|
|
|
{ |
|
|
|
var parsed = DateTime(value); |
|
|
|
if (parsed != null) return parsed.Value; |
|
|
|
|
|
|
|
return failed; |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Fixed
|
|
|
@ -211,40 +231,6 @@ namespace Apewer |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Text
|
|
|
|
|
|
|
|
/// <summary>解析文本,获取 DateTime 对象。</summary>
|
|
|
|
public static Class<DateTime> FromText(string text) |
|
|
|
{ |
|
|
|
var str = text; |
|
|
|
if (string.IsNullOrEmpty(str)) return null; |
|
|
|
|
|
|
|
var utc = false; |
|
|
|
var lower = str.ToLower(); |
|
|
|
if (lower.EndsWith(" utc")) |
|
|
|
{ |
|
|
|
utc = true; |
|
|
|
str = str.Substring(0, str.Length - 4); |
|
|
|
} |
|
|
|
|
|
|
|
DateTime dt; |
|
|
|
if (!TryParse(str, out dt)) |
|
|
|
{ |
|
|
|
if (!str.Contains("-") && TryParseExact(str, "yyyy-M-d", null, DateTimeStyles.None, out dt)) |
|
|
|
{ |
|
|
|
if (!str.Contains("/") && TryParseExact(str, "yyyy/M/d", null, DateTimeStyles.None, out dt)) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (utc) dt = new DateTime(dt.Ticks, DateTimeKind.Utc); |
|
|
|
return new Class<DateTime>(dt); |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region Lucid & Compact
|
|
|
|
|
|
|
|
/// <summary>表示当前本地时间的文本,显示为易于阅读的格式。</summary>
|
|
|
@ -358,68 +344,117 @@ namespace Apewer |
|
|
|
|
|
|
|
/// <summary>解析文本。</summary>
|
|
|
|
/// <param name="text">要被解析的文本。</param>
|
|
|
|
/// <param name="failed">解析失败时的获取方法。</param>
|
|
|
|
public static Nullable<DateTime> Parse(string text, Func<DateTime> failed = null) |
|
|
|
public static Class<DateTime> Parse(string text) |
|
|
|
{ |
|
|
|
if (string.IsNullOrEmpty(text)) return null; |
|
|
|
|
|
|
|
// 使用默认解析。
|
|
|
|
if (TryParse(text, out DateTime system)) return new Class<DateTime>(system); |
|
|
|
|
|
|
|
// 尝试解析 Lucid 格式。
|
|
|
|
var lucid = ParseLucid(text); |
|
|
|
if (lucid != null) return lucid; |
|
|
|
|
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>解析文本,获取 DateTime 对象。</summary>
|
|
|
|
static Class<DateTime> ParseExact(string text) |
|
|
|
{ |
|
|
|
var str = text; |
|
|
|
if (string.IsNullOrEmpty(str)) return null; |
|
|
|
|
|
|
|
var utc = false; |
|
|
|
var lower = str.ToLower(); |
|
|
|
if (lower.EndsWith(" utc")) |
|
|
|
{ |
|
|
|
if (TryParse(text, out DateTime dt)) return dt; |
|
|
|
utc = true; |
|
|
|
str = str.Substring(0, str.Length - 4); |
|
|
|
} |
|
|
|
|
|
|
|
// 尝试解析 Lucid 格式。
|
|
|
|
var byLucid = ParseLucid(text); |
|
|
|
if (byLucid != null) return byLucid; |
|
|
|
DateTime dt; |
|
|
|
if (!TryParse(str, out dt)) |
|
|
|
{ |
|
|
|
if (!str.Contains("-") && TryParseExact(str, "yyyy-M-d", null, DateTimeStyles.None, out dt)) |
|
|
|
{ |
|
|
|
if (!str.Contains("/") && TryParseExact(str, "yyyy/M/d", null, DateTimeStyles.None, out dt)) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 尝试 failed 回调。
|
|
|
|
if (failed != null) return failed.Invoke(); |
|
|
|
if (utc) dt = new DateTime(dt.Ticks, DateTimeKind.Utc); |
|
|
|
return new Class<DateTime>(dt); |
|
|
|
} |
|
|
|
|
|
|
|
return null; |
|
|
|
/// <summary>解析文本。</summary>
|
|
|
|
/// <param name="text">要被解析的文本。</param>
|
|
|
|
/// <param name="failed">解析失败时的获取方法。</param>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
public static DateTime Parse(string text, Func<DateTime> failed) |
|
|
|
{ |
|
|
|
if (failed == null) throw new ArgumentNullException(nameof(failed)); |
|
|
|
|
|
|
|
var parsed = Parse(text); |
|
|
|
if (parsed != null) return parsed.Value; |
|
|
|
|
|
|
|
return failed.Invoke(); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>解析文本。</summary>
|
|
|
|
/// <param name="text">要被解析的文本。</param>
|
|
|
|
/// <param name="failed">解析失败时的默认值。</param>
|
|
|
|
/// <exception cref="ArgumentNullException" />
|
|
|
|
public static DateTime Parse(string text, DateTime failed) |
|
|
|
{ |
|
|
|
var parsed = Parse(text); |
|
|
|
if (parsed != null) return parsed.Value; |
|
|
|
|
|
|
|
return failed; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>解析文本。</summary>
|
|
|
|
public static Nullable<DateTime> ParseLucid(string lucid) |
|
|
|
static Class<DateTime> ParseLucid(string lucid) |
|
|
|
{ |
|
|
|
var failed = null as Nullable<DateTime>; |
|
|
|
if (lucid.IsEmpty()) return failed; |
|
|
|
if (lucid.IsEmpty()) return null; |
|
|
|
|
|
|
|
int year = 0, month = 0, day = 0; |
|
|
|
if (lucid.Length < 10) return failed; |
|
|
|
if (lucid[4] != '-' || lucid[7] != '-') return failed; |
|
|
|
if (lucid.Length < 10) return null; |
|
|
|
if (lucid[4] != '-' || lucid[7] != '-') return null; |
|
|
|
year = NumberUtility.Int32(lucid.Substring(0, 4)); |
|
|
|
month = NumberUtility.Int32(lucid.Substring(5, 2)); |
|
|
|
day = NumberUtility.Int32(lucid.Substring(8, 2)); |
|
|
|
if (year < 1) return failed; |
|
|
|
if (month < 1 || month > 12) return failed; |
|
|
|
if (day < 1 || day > DaysInMonth(year, month)) return failed; |
|
|
|
if (year < 1) return null; |
|
|
|
if (month < 1 || month > 12) return null; |
|
|
|
if (day < 1 || day > DaysInMonth(year, month)) return null; |
|
|
|
|
|
|
|
int hour = 0, minute = 0, second = 0, milli = 0; |
|
|
|
if (lucid.Length >= 16) |
|
|
|
{ |
|
|
|
if (lucid[10] != ' ' || lucid[13] != ':') return failed; |
|
|
|
if (lucid[10] != ' ' || lucid[13] != ':') return null; |
|
|
|
hour = NumberUtility.Int32(lucid.Substring(11, 2)); |
|
|
|
minute = NumberUtility.Int32(lucid.Substring(14, 2)); |
|
|
|
if (hour < 0 || hour > 23) return failed; |
|
|
|
if (minute < 0 || minute > 59) return failed; |
|
|
|
if (hour < 0 || hour > 23) return null; |
|
|
|
if (minute < 0 || minute > 59) return null; |
|
|
|
|
|
|
|
if (lucid.Length >= 19) |
|
|
|
{ |
|
|
|
if (lucid[16] != ':') return failed; |
|
|
|
if (lucid[16] != ':') return null; |
|
|
|
second = NumberUtility.Int32(lucid.Substring(17, 2)); |
|
|
|
if (second < 0 || second > 59) return failed; |
|
|
|
if (second < 0 || second > 59) return null; |
|
|
|
|
|
|
|
if (lucid.Length >= 23) |
|
|
|
{ |
|
|
|
if (lucid[19] != '.') return failed; |
|
|
|
if (lucid[19] != '.') return null; |
|
|
|
milli = NumberUtility.Int32(lucid.Substring(20, 3)); |
|
|
|
if (milli < 0 || milli > 999) return failed; |
|
|
|
if (milli < 0 || milli > 999) return null; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var entity = new DateTime(year, month, day, hour, minute, second, milli); |
|
|
|
return new Nullable<DateTime>(entity); |
|
|
|
return new Class<DateTime>(entity); |
|
|
|
} |
|
|
|
|
|
|
|
#endregion
|
|
|
|