在C#中處理時(shí)間戳和時(shí)區(qū)的解決方法
介紹
處理時(shí)間戳和不同的時(shí)區(qū)可能是軟件開發(fā)中的一個(gè)棘手問題。尤其是當(dāng)系統(tǒng)不確定給定的日期時(shí)間是UTC還是本地時(shí)間時(shí),通常會(huì)遇到與時(shí)間轉(zhuǎn)換相關(guān)的問題。在這篇文章中,我將分享我們?nèi)绾卧贑#應(yīng)用程序中使用Unix時(shí)間來(lái)簡(jiǎn)化時(shí)間管理的經(jīng)驗(yàn)。
問題
在我們的工作中,經(jīng)常遇到系統(tǒng)對(duì)給定的日期時(shí)間是UTC還是本地時(shí)間感到困惑,從而導(dǎo)致幾個(gè)小時(shí)的時(shí)間差異。這在不同時(shí)間格式和時(shí)區(qū)之間進(jìn)行轉(zhuǎn)換時(shí)尤其問題嚴(yán)重。
我們的解決方案
為了解決這些問題,我們決定使用Unix時(shí)間(以秒或毫秒為單位)來(lái)替換數(shù)據(jù)庫(kù)中的日期時(shí)間或字符串表示。Unix時(shí)間是一種定義明確的、與時(shí)區(qū)無(wú)關(guān)的時(shí)間表示方法,這使得時(shí)間處理和轉(zhuǎn)換變得更容易。
實(shí)現(xiàn)Timestamp類
在我們的C#代碼中,我們創(chuàng)建了一個(gè)封裝Unix時(shí)間(以毫秒為單位)的Timestamp類。這個(gè)類提供了各種方法來(lái)轉(zhuǎn)換為其他時(shí)間格式或從其他時(shí)間格式轉(zhuǎn)換,確保所有時(shí)間操作的一致性和正確性。
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)換的擴(kuò)展方法
我們還創(chuàng)建了擴(kuò)展方法,用于在不同時(shí)間格式之間進(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;
}
// 其他擴(kuò)展方法...
}
在主邏輯中使用Timestamp類
在我們的主應(yīng)用程序邏輯中,我們專門使用Timestamp類來(lái)表示時(shí)間。這種方法幫助我們避免了與時(shí)間轉(zhuǎn)換相關(guān)的任何問題,因?yàn)樗械臅r(shí)間相關(guān)數(shù)據(jù)都以一致的格式存儲(chǔ)和處理。
以下是我們?cè)诖a中使用Timestamp類的示例:
public class ExampleService
{
public void ProcessData()
{
// 獲取當(dāng)前時(shí)間作為Timestamp
Timestamp currentTime = Timestamp.CurrentTimestamp();
// 將Timestamp轉(zhuǎn)換為DateTime以便顯示
DateTime displayTime = currentTime.ToDateTimeUTC();
// 記錄當(dāng)前時(shí)間
Console.WriteLine($"當(dāng)前時(shí)間: {currentTime.ToLabel()}");
}
}
在數(shù)據(jù)庫(kù)視圖(View)中轉(zhuǎn)換Unix時(shí)間
為了方便讀懂?dāng)?shù)據(jù)庫(kù)中Unix時(shí)間,可以創(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ù)并將其映射到對(duì)象時(shí),可以在數(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時(shí)間和專門的Timestamp類,我們實(shí)現(xiàn)了以下幾個(gè)好處:
- 一致性:所有時(shí)間數(shù)據(jù)都以一致的、與時(shí)區(qū)無(wú)關(guān)的格式表示。
- 簡(jiǎn)便性:封裝在
Timestamp類中的轉(zhuǎn)換方法簡(jiǎn)化了時(shí)間操作。 - 清晰性:代碼中明確顯示所有時(shí)間數(shù)據(jù)都以統(tǒng)一的方式處理,從而減少了錯(cuò)誤的風(fēng)險(xiǎn)。
結(jié)論
處理時(shí)間戳和時(shí)區(qū)可能很復(fù)雜,但通過使用Unix時(shí)間并將其封裝在Timestamp類中,我們簡(jiǎn)化了時(shí)間管理并避免了許多常見的陷阱。我希望這種方法也能幫助到你的項(xiàng)目。
以上就是在C#中處理時(shí)間戳和時(shí)區(qū)的解決方法的詳細(xì)內(nèi)容,更多關(guān)于C#處理時(shí)間戳和時(shí)區(qū)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用C#創(chuàng)建Windows服務(wù)的實(shí)例代碼
這篇文章主要介紹了使用C#創(chuàng)建Windows服務(wù)的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2017-07-07
使用GetInvalidFileNameCharts生成文件名
這篇文章主要介紹了一個(gè)很實(shí)用的函數(shù)Path.GetInvalidFileNameCharts(),他可以很方便的生成一個(gè)有效的文件名稱2014-01-01
C#實(shí)現(xiàn)在服務(wù)器端裁剪圖片的方法
這篇文章主要介紹了C#實(shí)現(xiàn)在服務(wù)器端裁剪圖片的方法,涉及C#操作圖片的相關(guān)技巧,需要的朋友可以參考下2015-04-04

