簡體   English   中英

將DateTime轉換為UTC時遇到問題

[英]Having problems with converting my DateTime to UTC

我將所有日期都以UTC格式存儲在我的數據庫中。 我問用戶他們的時區,我想使用他們的時區加上我猜測的服務器時間來計算他們的UTC。

一旦我有了,我想搜索一下,使用新轉換的UTC日期查看數據庫中的范圍。

但我總是得到這個例外。

System.ArgumentException was unhandled by user code  
Message="The conversion could not be completed because the   
supplied DateTime did not have the Kind property set correctly.  
For example, when the Kind property is DateTimeKind.Local,   
the source time zone must be TimeZoneInfo.Local.  
Parameter name: sourceTimeZone"

我不知道為什么我會這樣做。

我試過兩種方法

 TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(id);
 // I also tried DateTime.UtcNow
 DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); 
 var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone );

這失敗了所以我累了

 DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); 
 var utc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(now, 
                                           ZoneId, TimeZoneInfo.Utc.Id);

這也失敗了同樣的錯誤。 我究竟做錯了什么?

編輯會這樣嗎?

 DateTime localServerTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
 TimeZoneInfo info = TimeZoneInfo.FindSystemTimeZoneById(id);

 var usersTime = TimeZoneInfo.ConvertTime(localServerTime, info);

 var utc = TimeZoneInfo.ConvertTimeToUtc(usersTime, userInfo);

編輯2 @ Jon Skeet

我只是在考慮我甚至不需要做這一切。 時間的東西現在讓我困惑,所以這就是為什么帖子可能不如它應該的那樣清晰。 我永遠都不知道DateTime.Now到底是什么(我試圖將我的時區更改為另一個時區,並且它一直保持當地時間)。

這就是我想要的東西。 用戶來到網站添加一些警報,它現在保存為utc(在它之前是DateTime.Now然后有人建議存儲所有UTC)。

因此,在用戶訪問我的網站之前,根據我的托管服務器的位置,它可能就像第二天一樣。 因此,如果警報據說是在8月30日(他們的時間)顯示,但是服務器的時差可以在8月29日到來,並且會顯示警報。

所以我想打擊那個。 所以現在我不確定我是否應該存儲他們的當地時間然后使用這個偏移的東西? 或者只存儲UTC時間。 僅僅存儲UTC時間仍然可能是錯誤的,因為用戶仍然可能在當地時間考慮並且我不確定UTC如何真正起作用它仍然可能最終導致時間差異。

EDIT3

 var info = TimeZoneInfo.FindSystemTimeZoneById(id)

 DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(DataBaseUTCDate,
                                             TimeZoneInfo.Utc, info);

您需要將Kind設置為Unspecified ,如下所示:

DateTime now = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);
var utc = TimeZoneInfo.ConvertTimeToUtc(now , zone);

DateTimeKind.Local表示本地時區,而不是任何其他時區。 這就是你得到錯誤的原因。

DateTime結構僅支持兩個時區:

  • 機器運行的本地時區。
  • 和UTC。

看看DateTimeOffset結構。

var info = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");

DateTimeOffset localServerTime = DateTimeOffset.Now;

DateTimeOffset usersTime = TimeZoneInfo.ConvertTime(localServerTime, info);

DateTimeOffset utc = localServerTime.ToUniversalTime();

Console.WriteLine("Local Time:  {0}", localServerTime);
Console.WriteLine("User's Time: {0}", usersTime);
Console.WriteLine("UTC:         {0}", utc);

輸出:

Local Time:  30.08.2009 20:48:17 +02:00
User's Time: 31.08.2009 03:48:17 +09:00
UTC:         30.08.2009 18:48:17 +00:00

正如dtb所說,如果要存儲具有特定時區的日期/時間,則應使用DateTimeOffset

但是,從你的帖子中可以清楚地知道你真的需要這樣做。 您只使用DateTime.Now提供示例,並且您說您猜測您正在使用服務器時間。 你幾點想要什么時間? 如果您只想要UTC中的當前時間,請使用DateTime.UtcNowDateTimeOffset.UtcNow 你不需要知道時區就知道當前的UTC時間,正是因為它是通用的。

如果您以其他方式從用戶那里獲得日期/時間,請提供更多信息 - 這樣我們就能夠確定您需要做的事情。 否則我們只是在猜測。

其他人的答案似乎過於復雜。 我有一個特定的要求,這對我來說很好:

void Main()
{
    var startDate = DateTime.Today;
    var StartDateUtc = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.SpecifyKind(startDate.Date, DateTimeKind.Unspecified), "Eastern Standard Time", "UTC");
    startDate.Dump();
    StartDateUtc.Dump();
}

哪個輸出(來自linqpad)我的預期:

12/20/2013 12:00:00 AM

12/20/2013 5:00:00 AM

對於未指明類型的提示,道具為Slaks。 這就是我所缺少的。 但所有關於只有兩種日期(本地和UTC)的討論都讓我感到困惑。

僅供參考 - 我運行的機器是在中部時區,而DST沒有生效。

UTC只是每個人都同意作為標准時區的時區。 具體來說,這是一個包含英國倫敦的時區。 編輯 :請注意,它不是完全相同的時區; 例如,UTC沒有DST。 (謝謝,Jon Skeet)

關於UTC的唯一特殊之處在於它在.Net中使用比任何其他時區( DateTime.UtcNowDateTime.ToUniversalTime和其他成員)更容易。

因此,正如其他人所提到的,最好的辦法是在數據庫中存儲UTC的所有日期,然后轉換為用戶的本地時間(通過在顯示之前寫入TimeZoneInfo.ConvertTime(time, usersTimeZone)


如果您想成為更好的,您可以對用戶的IP地址進行地理定位,以自動猜測他們的時區。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM