在C#中處理時間戳和時區(qū)的解決方法
介紹
處理時間戳和不同的時區(qū)可能是軟件開發(fā)中的一個棘手問題。尤其是當系統(tǒng)不確定給定的日期時間是UTC還是本地時間時,通常會遇到與時間轉(zhuǎn)換相關(guān)的問題。在這篇文章中,我將分享我們?nèi)绾卧贑#應(yīng)用程序中使用Unix時間來簡化時間管理的經(jīng)驗。
問題
在我們的工作中,經(jīng)常遇到系統(tǒng)對給定的日期時間是UTC還是本地時間感到困惑,從而導(dǎo)致幾個小時的時間差異。這在不同時間格式和時區(qū)之間進行轉(zhuǎ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)建了擴展方法,用于在不同時間格式之間進行轉(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()
{
// 獲取當前時間作為Timestamp
Timestamp currentTime = Timestamp.CurrentTimestamp();
// 將Timestamp轉(zhuǎn)換為DateTime以便顯示
DateTime displayTime = currentTime.ToDateTimeUTC();
// 記錄當前時間
Console.WriteLine($"當前時間: {currentTime.ToLabel()}");
}
}
在數(shù)據(jù)庫視圖(View)中轉(zhuǎn)換Unix時間
為了方便讀懂數(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)一的方式處理,從而減少了錯誤的風險。
結(jié)論
處理時間戳和時區(qū)可能很復(fù)雜,但通過使用Unix時間并將其封裝在Timestamp類中,我們簡化了時間管理并避免了許多常見的陷阱。我希望這種方法也能幫助到你的項目。
以上就是在C#中處理時間戳和時區(qū)的解決方法的詳細內(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

