在C#中處理時間戳和時區(qū)的解決方法
介紹
處理時間戳和不同的時區(qū)可能是軟件開發(fā)中的一個棘手問題。尤其是當(dāng)系統(tǒng)不確定給定的日期時間是UTC還是本地時間時,通常會遇到與時間轉(zhuǎn)換相關(guān)的問題。在這篇文章中,我將分享我們?nèi)绾卧贑#應(yīng)用程序中使用Unix時間來簡化時間管理的經(jīng)驗。
問題
在我們的工作中,經(jīng)常遇到系統(tǒng)對給定的日期時間是UTC還是本地時間感到困惑,從而導(dǎo)致幾個小時的時間差異。這在不同時間格式和時區(qū)之間進(jìn)行轉(zhuǎn)換時尤其問題嚴(yán)重。
我們的解決方案
為了解決這些問題,我們決定使用Unix時間(以秒或毫秒為單位)來替換數(shù)據(jù)庫中的日期時間或字符串表示。Unix時間是一種定義明確的、與時區(qū)無關(guān)的時間表示方法,這使得時間處理和轉(zhuǎn)換變得更容易。
實現(xiàn)Timestamp類
在我們的C#代碼中,我們創(chuàng)建了一個封裝Unix時間(以毫秒為單位)的Timestamp
類。這個類提供了各種方法來轉(zhuǎn)換為其他時間格式或從其他時間格式轉(zhuǎn)換,確保所有時間操作的一致性和正確性。
Timestamp類定義
以下是我們定義的Timestamp
類:
public class Timestamp { public double UnixTime_ms { get; set; } = 0.0; public static DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public static Timestamp CurrentTimestamp() { return FromDateTimeUTC(DateTime.UtcNow); } public static Timestamp FromUnixTimeSec(double unix_s) { return new Timestamp() { UnixTime_ms = unix_s * 1000.0, }; } public static Timestamp FromUnixTimeMilliSec(double unix_ms) { return new Timestamp() { UnixTime_ms = unix_ms, }; } public static Timestamp FromDateTimeUTC(DateTime dateTime) { if (dateTime.Kind == DateTimeKind.Unspecified) { dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); } return new Timestamp() { UnixTime_ms = (dateTime - UnixEpoch).TotalMilliseconds }; } public static Timestamp FromTimestampUTC(string timestampUTC) { bool tryDateTime = DateTime.TryParse(timestampUTC, out DateTime res); if (tryDateTime) { long unixMs = new DateTimeOffset(res.ToUniversalTime()).ToUnixTimeMilliseconds(); return new Timestamp() { UnixTime_ms = unixMs, }; } else { return new Timestamp(); } } public override bool Equals(object obj) { return obj is Timestamp timestamp && UnixTime_ms == timestamp.UnixTime_ms; } public override int GetHashCode() { return -262018729 + UnixTime_ms.GetHashCode(); } public static bool operator ==(Timestamp left, Timestamp right) { return EqualityComparer<Timestamp>.Default.Equals(left, right); } public static bool operator !=(Timestamp left, Timestamp right) { return !(left == right); } public static bool operator >(Timestamp left, Timestamp right) { return left.UnixTime_ms > right.UnixTime_ms; } public static bool operator <(Timestamp left, Timestamp right) { return left.UnixTime_ms < right.UnixTime_ms; } public static bool operator >=(Timestamp left, Timestamp right) { return left.UnixTime_ms >= right.UnixTime_ms; } public static bool operator <=(Timestamp left, Timestamp right) { return left.UnixTime_ms <= right.UnixTime_ms; } }
轉(zhuǎn)換的擴展方法
我們還創(chuàng)建了擴展方法,用于在不同時間格式之間進(jìn)行轉(zhuǎn)換:
public static class TimestampExtensions { private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public static double ToUnixS(this Timestamp timestamp) => timestamp.UnixTime_ms / 1000.0; public static double ToUnixMins(this Timestamp timestamp) => timestamp.UnixTime_ms / 60000.0; public static DateTime ToDateTimeUTC(this Timestamp timestamp) => UnixEpoch.AddMilliseconds(timestamp.UnixTime_ms).ToUniversalTime(); public static string ToLabel(this Timestamp timestamp) => timestamp.ToDateTimeUTC().ToString("yyyy/MM/dd h:mm:ss tt"); public static bool IsWithinRange(this Timestamp timestamp, Timestamp startTime, Timestamp endTime) { if (timestamp == null || startTime == null || endTime == null) { return false; } return timestamp.UnixTime_ms >= startTime.UnixTime_ms && timestamp.UnixTime_ms <= endTime.UnixTime_ms; } // 其他擴展方法... }
在主邏輯中使用Timestamp類
在我們的主應(yīng)用程序邏輯中,我們專門使用Timestamp
類來表示時間。這種方法幫助我們避免了與時間轉(zhuǎn)換相關(guān)的任何問題,因為所有的時間相關(guān)數(shù)據(jù)都以一致的格式存儲和處理。
以下是我們在代碼中使用Timestamp
類的示例:
public class ExampleService { public void ProcessData() { // 獲取當(dāng)前時間作為Timestamp Timestamp currentTime = Timestamp.CurrentTimestamp(); // 將Timestamp轉(zhuǎn)換為DateTime以便顯示 DateTime displayTime = currentTime.ToDateTimeUTC(); // 記錄當(dāng)前時間 Console.WriteLine($"當(dāng)前時間: {currentTime.ToLabel()}"); } }
在數(shù)據(jù)庫視圖(View)中轉(zhuǎn)換Unix時間
為了方便讀懂?dāng)?shù)據(jù)庫中Unix時間,可以創(chuàng)建處理這些轉(zhuǎn)換的視圖(View)。以下是在SQL Server中的示例:
CREATE VIEW dbo.ExampleView AS SELECT Id, Name, Description, DATEADD(MILLISECOND, UnixTime_ms, '1970-01-01 00:00:00') AS DateTimeValue FROM dbo.ExampleTable;
在C#數(shù)據(jù)訪問層(DAO)中映射轉(zhuǎn)換
在查詢數(shù)據(jù)并將其映射到對象時,可以在數(shù)據(jù)訪問層中處理這些轉(zhuǎn)換:
public class ExampleRepository { private readonly string connectionString; public ExampleRepository(string connectionString) { this.connectionString = connectionString; } public ExampleModel GetExampleById(int id) { using (var connection = new SqlConnection(connectionString)) { string query = "SELECT Id, Name, Description, UnixTime_ms FROM ExampleTable WHERE Id = @Id"; var exampleData = connection.QuerySingleOrDefault(query, new { Id = id }); if (exampleData != null) { return new ExampleModel { Id = exampleData.Id, Name = exampleData.Name, Description = exampleData.Description, Timestamp = Timestamp.FromUnixTimeMilliSec(exampleData.UnixTime_ms) }; } return null; } } }
這種方法的好處
通過使用Unix時間和專門的Timestamp
類,我們實現(xiàn)了以下幾個好處:
- 一致性:所有時間數(shù)據(jù)都以一致的、與時區(qū)無關(guān)的格式表示。
- 簡便性:封裝在
Timestamp
類中的轉(zhuǎn)換方法簡化了時間操作。 - 清晰性:代碼中明確顯示所有時間數(shù)據(jù)都以統(tǒng)一的方式處理,從而減少了錯誤的風(fēng)險。
結(jié)論
處理時間戳和時區(qū)可能很復(fù)雜,但通過使用Unix時間并將其封裝在Timestamp
類中,我們簡化了時間管理并避免了許多常見的陷阱。我希望這種方法也能幫助到你的項目。
以上就是在C#中處理時間戳和時區(qū)的解決方法的詳細(xì)內(nèi)容,更多關(guān)于C#處理時間戳和時區(qū)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用C#創(chuàng)建Windows服務(wù)的實例代碼
這篇文章主要介紹了使用C#創(chuàng)建Windows服務(wù)的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07使用GetInvalidFileNameCharts生成文件名
這篇文章主要介紹了一個很實用的函數(shù)Path.GetInvalidFileNameCharts(),他可以很方便的生成一個有效的文件名稱2014-01-01