C# 时间格式化工具类
using System;
using System.Globalization;
using System.Reflection;
namespace System
{
public sealed class DateTimeUtils
{
/// <summary> 日期格式 <c>[yyyy-MM-dd]</c> </summary>
public static readonly DateTimeUtils DATE = new DateTimeUtils("yyyy-MM-dd");
/// <summary> 日期格式 <c>[yyyyMMdd]</c> </summary>
public static readonly DateTimeUtils DATE_COMPACT = new DateTimeUtils("yyyyMMdd");
/// <summary> 日期格式 <c>[yyyy_MM_dd]</c> </summary>
public static readonly DateTimeUtils DATE_UNDERLINE = new DateTimeUtils("yyyy_MM_dd");
/// <summary> 时间格式 <c>[HH:mm:ss]</c> </summary>
public static readonly DateTimeUtils TIME = new DateTimeUtils("HH:mm:ss");
/// <summary> 时间格式 <c>[HHmmss]</c> </summary>
public static readonly DateTimeUtils TIME_COMPACT = new DateTimeUtils("HHmmss");
/// <summary> 时间格式 <c>[HH_mm_ss]</c> </summary>
public static readonly DateTimeUtils TIME_UNDERLINE = new DateTimeUtils("HH_mm_ss");
/// <summary> 时间格式 <c>[HH:mm:ss.fff]</c> </summary>
public static readonly DateTimeUtils TIME_MILLI = new DateTimeUtils("HH:mm:ss.fff");
/// <summary> 时间格式 <c>[HHmmssfff]</c> </summary>
public static readonly DateTimeUtils TIME_MILLI_COMPACT = new DateTimeUtils("HHmmssfff");
/// <summary> 时间格式 <c>[HH_mm_ss_fff]</c> </summary>
public static readonly DateTimeUtils TIME_MILLI_UNDERLINE = new DateTimeUtils("HH_mm_ss_fff");
/// <summary> 日期时间格式 <c>[yyyy-MM-dd HH:mm:ss]</c> </summary>
public static readonly DateTimeUtils DATE_TIME = new DateTimeUtils("yyyy-MM-dd HH:mm:ss");
/// <summary> 日期时间格式 <c>[yyyyMMddHHmmss]</c> </summary>
public static readonly DateTimeUtils DATE_TIME_COMPACT = new DateTimeUtils("yyyyMMddHHmmss");
/// <summary> 日期时间格式 <c>[yyyy_MM_dd_HH_mm_ss]</c> </summary>
public static readonly DateTimeUtils DATE_TIME_UNDERLINE = new DateTimeUtils("yyyy_MM_dd_HH_mm_ss");
/// <summary> 日期时间格式 <c>[yyyy-MM-dd HH:mm:ss.fff]</c> </summary>
public static readonly DateTimeUtils DATE_TIME_MILLI = new DateTimeUtils("yyyy-MM-dd HH:mm:ss.fff");
/// <summary> 日期时间格式 <c>[yyyyMMddHHmmssfff]</c> </summary>
public static readonly DateTimeUtils DATE_TIME_MILLI_COMPACT = new DateTimeUtils("yyyyMMddHHmmssfff");
/// <summary> 日期时间格式 <c>[yyyy_MM_dd_HH_mm_ss_fff]</c> </summary>
public static readonly DateTimeUtils DATE_TIME_MILLI_UNDERLINE = new DateTimeUtils("yyyy_MM_dd_HH_mm_ss_fff");
// ----------------------------------------------------------------------------------------------
private const int DAYS_PER_WEEK = 7;
private const long TICKS_PER_SEC = 10000000L;
private const long TICKS_PER_MILLISEC = 10000L;
private const long UNIX_EPOCH_TICKS = 621355968000000000L;
private readonly string _pattern;
private DateTimeUtils() {}
private DateTimeUtils(string pattern)
{
_pattern = pattern;
}
// ----------------------------------------------------------------------------------------------
/// <summary>
/// Formats a date-time object using this formatter.
/// </summary>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <returns>the formatted string, not null</returns>
public string Now()
{
return Format(DateTime.Now);
}
/// <summary>
/// Formats a date-time object using this formatter.
/// </summary>
/// <param name="datetime">the date-time object to format, not null</param>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <returns>the formatted string, not null</returns>
public string Format(DateTime datetime)
{
return datetime.ToString(_pattern, DateTimeFormatInfo.InvariantInfo);
}
/// <summary>
/// Formats a date-time object using this formatter.
/// </summary>
/// <param name="epochSecond">the epoch seconds to format, not null</param>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>the formatted string, not null</returns>
public string FormatEpochSecond(long epochSecond)
{
return Format(OfEpochSecond(epochSecond));
}
/// <summary>
/// Formats a date-time object using this formatter.
/// </summary>
/// <param name="epochMilli">the epoch milliseconds to format, not null</param>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>the formatted string, not null</returns>
public string FormatEpochMilli(long epochMilli)
{
return Format(OfEpochMilli(epochMilli));
}
// ----------------------------------------------------------------------------------------------
/// <summary>
/// Fully parses the text producing an object of the specified type.
/// </summary>
/// <param name="datetime">the text to parse, not null</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <returns>the parsed date-time, not null</returns>
public DateTime Parse(string datetime)
{
return DateTime.ParseExact(datetime, _pattern, CultureInfo.InvariantCulture);
}
/// <summary>
/// Fully parses the text producing an object of the specified type.
/// </summary>
/// <param name="datetime">the text to parse, not null</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <returns>the parsed time-stamp</returns>
public long ParseEpochSecond(string datetime)
{
return ToEpochSecond(Parse(datetime));
}
/// <summary>
/// Fully parses the text producing an object of the specified type.
/// </summary>
/// <param name="datetime">the text to parse, not null</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <returns>the parsed time-stamp</returns>
public long ParseEpochMilli(string datetime)
{
return ToEpochMilli(Parse(datetime));
}
// ----------------------------------------------------------------------------------------------
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="years">the years to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddYears(string datetime, int years)
{
return Format(Parse(datetime).AddYears(years));
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="months">the months to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddMonths(string datetime, int months)
{
return Format(Parse(datetime).AddMonths(months));
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="weeks">the weeks to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddWeeks(string datetime, int weeks)
{
return AddDays(datetime, weeks * DAYS_PER_WEEK);
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="days">the days to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddDays(string datetime, int days)
{
return Format(Parse(datetime).AddDays(days));
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="hours">the hours to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddHours(string datetime, int hours)
{
return Format(Parse(datetime).AddHours(hours));
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="minutes">the minutes to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddMinutes(string datetime, int minutes)
{
return Format(Parse(datetime).AddMinutes(minutes));
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="seconds">the seconds to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddSeconds(string datetime, int seconds)
{
return Format(Parse(datetime).AddSeconds(seconds));
}
/// <summary>
/// Returns a copy of this <tt>date-time</tt> with the specified number of years added.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="milliseconds">the milliseconds to add, may be negative</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>based on this date-time with the years added, not null</returns>
public string AddMilliseconds(string datetime, int milliseconds)
{
return Format(Parse(datetime).AddMilliseconds(milliseconds));
}
// ----------------------------------------------------------------------------------------------
/// <summary>
/// Checks if the year is a leap year, according to the ISO proleptic calendar system rules.
/// This method applies the current rules for leap years across the whole time-line.
/// In general, a year is a leap year if it is divisible by four without remainder.
/// However, years divisible by 100, are not leap years, with the exception of years divisible by 400 which are.
/// The calculation is proleptic - applying the same rules into the far future and far past.
/// This is historically inaccurate, but is correct for the ISO-8601 standard.
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <returns>true if the year is leap, false otherwise</returns>
public bool IsLeapYear(string datetime)
{
return IsLeapYear(Parse(datetime));
}
/// <summary>
/// Checks if this date-time is after the specified date-time.
/// </summary>
/// <param name="source">date-time of the String type</param>
/// <param name="target">the date-time object to compare to</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <returns>true if this date-time is after the specified date-time</returns>
public bool IsAfter(string source, DateTime target)
{
return Parse(source) > target;
}
/// <summary>
/// Checks if this date-time is before the specified date-time.
/// </summary>
/// <param name="source">date-time of the String type</param>
/// <param name="target">the date-time object to compare to</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <returns>true if this date-time is before the specified date-time</returns>
public bool IsBefore(string source, DateTime target)
{
return Parse(source) < target;
}
/// <summary>
/// Checks if this date-time is equal to the specified date-time.
/// </summary>
/// <param name="source">date-time of the String type</param>
/// <param name="target">the date-time object to compare to</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <returns>true if this date-time is equal to the specified date-time</returns>
public bool IsEqual(string source, DateTime target)
{
return Parse(source) == target;
}
/// <summary>
/// Change the format of the date display
/// </summary>
/// <param name="datetime">date-time of the String type</param>
/// <param name="pattern">the format of the date display</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="FormatException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <returns></returns>
public string Transform(string datetime, string pattern)
{
return Parse(datetime).ToString(pattern, DateTimeFormatInfo.InvariantInfo);
}
// ----------------------------------------------------------------------------------------------
/// <summary>
/// Checks if the year is a leap year, according to the ISO proleptic calendar system rules.
/// This method applies the current rules for leap years across the whole time-line.
/// In general, a year is a leap year if it is divisible by four without remainder.
/// However, years divisible by 100, are not leap years, with the exception of years divisible by 400 which are.
/// The calculation is proleptic - applying the same rules into the far future and far past.
/// This is historically inaccurate, but is correct for the ISO-8601 standard.
/// </summary>
/// <param name="datetime">the date-time object</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <returns>true if the year is leap, false otherwise</returns>
public static bool IsLeapYear(DateTime datetime)
{
//return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0 && year % 3200 != 0);
return DateTime.IsLeapYear(datetime.Year);
}
/// <summary>
/// Convert the epoch seconds to date-time object.
/// </summary>
/// <param name="epochSecond">the epoch seconds to convert</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>the parsed date-time</returns>
public static DateTime OfEpochSecond(long epochSecond)
{
// ticks = 621355968000000000L + epochSecond * 10000000L;
var ticks = UNIX_EPOCH_TICKS + epochSecond * TICKS_PER_SEC;
return new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();
}
/// <summary>
/// Convert the epoch milliseconds to date-time object.
/// </summary>
/// <param name="epochMilli">the epoch milliseconds to convert</param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
/// <exception cref="ArgumentException"></exception>
/// <returns>the parsed date-time</returns>
public static DateTime OfEpochMilli(long epochMilli)
{
// ticks = 621355968000000000L + epochMilli * 10000L;
var ticks = UNIX_EPOCH_TICKS + epochMilli * TICKS_PER_MILLISEC;
return new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();
}
/// <summary>
/// Convert the date-time object to epoch seconds.
/// </summary>
/// <param name="datetime">the date-time object to convert, not null</param>
/// <returns>the parsed time-stamp</returns>
public static long ToEpochSecond(DateTime datetime)
{
// epochSecond = (ticks - 621355968000000000L) / 10000000L;
return (datetime.ToUniversalTime().Ticks - UNIX_EPOCH_TICKS) / TICKS_PER_SEC;
}
/// <summary>
/// Convert the date-time object to epoch milliseconds.
/// </summary>
/// <param name="datetime">the date-time object to convert, not null</param>
/// <returns>the parsed time-stamp</returns>
public static long ToEpochMilli(DateTime datetime)
{
// epochMilli = (ticks - 621355968000000000L) / 10000L;
return (datetime.ToUniversalTime().Ticks - UNIX_EPOCH_TICKS) / TICKS_PER_MILLISEC;
}
/// <summary>
/// Returns the current time in milliseconds.
/// Note thatwhile the unit of time of the return value is a millisecond,the granularity
/// of the value depends on the underlyingoperating system and may be larger.
/// For example, manyoperating systems measure time in units of tens ofmilliseconds.
/// </summary>
/// <returns>the difference, measured in milliseconds, betweenthe current time and midnight, January 1, 1970 UTC.</returns>
public static long CurrentTimeMillis()
{
return ToEpochMilli(DateTime.Now);
}
/// <summary>
/// Set the global time pattern for display.
/// </summary>
/// <param name="pattern">the time pattern</param>
public static void SetGlobalPattern(string pattern = "yyyy-MM-dd HH:mm:ss")
{
if (DateTimeFormatInfo.CurrentInfo != null)
{
var type = DateTimeFormatInfo.CurrentInfo.GetType();
if (type != null)
{
var field = type.GetField("generalLongTimePattern", BindingFlags.NonPublic | BindingFlags.Instance);
if (field != null)
{
field.SetValue(DateTimeFormatInfo.CurrentInfo, pattern);
}
}
}
}
}
}