2012-03-02 61 views
1

我寫了兩個擴展方法將時間從本地時間轉換爲UTC並返回。這是我有:轉換時區的c#擴展方法

public static DateTime ConvertUserTimeToUTCTime(this DateTime TheUserTime, string TheTimezoneID) 
{ 
    TheUserTime = new DateTime(TheUserTime.Year, TheUserTime.Month, 
     TheUserTime.Day, TheUserTime.Hour, TheUserTime.Minute, 
     TheUserTime.Second, DateTimeKind.Local); 

    TimeZoneInfo TheTZ = TimeZoneInfo.FindSystemTimeZoneById(TheTimezoneID); 
    TimeSpan TheOffset = TheTZ.GetUtcOffset(TheUserTime); 

    DateTimeOffset TheUTCTimeOffset = new DateTimeOffset(
     TheUserTime, TheOffset).ToUniversalTime(); 

    DateTime TheUTCTime = new DateTime(TheUTCTimeOffset.Year, 
     TheUTCTimeOffset.Month, TheUTCTimeOffset.Day, TheUTCTimeOffset.Hour, 
     TheUTCTimeOffset.Minute, 0, DateTimeKind.Utc); 

    return TheUTCTime; 
} 




public static DateTime ConvertUTCTimeToUserTime(this DateTime TheUTCTime, 
    string TheTimezoneID) 
{ 
    TimeZoneInfo TheTZ = TimeZoneInfo.FindSystemTimeZoneById(TheTimezoneID); 

    DateTime UTCTime = new DateTime(TheUTCTime.Year, TheUTCTime.Month, 
     TheUTCTime.Day, TheUTCTime.Hour, TheUTCTime.Minute, 0, DateTimeKind.Utc); 

    DateTime TheUserTime = TimeZoneInfo.ConvertTime(UTCTime, TheTZ); 

    return TheUserTime; 
} 

我在我的應用程序中使用這兩個很頻繁,我想知道他們是否線程安全。另外,將這兩個方法放在抽象類中,然後讓所有涉及時間操作的類都繼承自這個抽象類,會有什麼好處嗎?

感謝您對此次轉換主題的建議。

+0

我通常把我所有的擴展方法到一個單一的類,幷包括名字空間,無論我需要一個擴展方法。這樣任何可能需要這個擴展的DateTime對象都可以訪問它們。我討厭爲此燒基類,因爲它可以在運行時「混入」。 – 2012-03-02 18:29:13

回答

3

是的,它們是線程安全的。它們在變量命名(爲什麼「The」在所有事情之前,爲什麼是Pascal-casing?)方面都很醜陋,你應該考慮使用DateTime.SpecifyKind,但它們沒有做任何共享狀態......除非TimeZoneInfo有線程安全問題,應該沒事。 (TimeZoneInfo實際上指定實例成員保證是線程安全的,但它也指出是不可變的。我倒是希望是線程安全的。)

你肯定不該」 t將這些放在一個抽象類中作爲基類 - 這將是對繼承的濫用。它不是真的代表你想要專門化的一些抽象概念,是嗎?這裏的擴展方法是合理的。

你也應該覺得很仔細你如何想在第一種方法中的代碼不明確或無效的轉換情況下的行爲:例如,如果時鐘前進凌晨1點至凌晨2點,然後上午1:30在那一天的時區內無效。同樣,如果從凌晨2點回到凌晨1點,那麼凌晨1點半會發生兩次。查看TimeZoneInfo.GetUtcOffset的文檔以確保從其返回的值是您在這些情況下所需的值。

最後,請考慮使用Noda Time,而不是我的替代.NET日期/時間API(我相信)保持事情更清潔 - 並且讓您的日期/時間轉換非常明確。

(我只是前幾天寫了blog post about this very topic,在我一直在思考的API。反饋歡迎的選擇方面。)

+0

好的,謝謝你的線程安全輸入和保持我的擴展方法的建議。這個時區的概念真的很讓人困惑!希望有一個原生的.net功能來切換時區:提供日期時間和時區並返回日期時間。至於符號,我在處理一個對象的實例的時候放了這個符號;其他人寫了_myVariable,我覺得很奇怪。我猜的風格問題。 – frenchie 2012-03-02 18:47:46

+0

@frenchie:對我來說這似乎有點多餘 - 尤其是當您在單個方法調用中多次使用「The」時。至於「本地.NET功能來切換時區」 - 這正是'TimeZoneInfo.ConvertTime'的作用,但您需要小心如何使用它。這是因爲'DateTime'基本上被打破 - 請參閱http://noda-time.blogspot.com/2011/08/what-wrong-with-datetime-anyway.html – 2012-03-02 18:54:35

+0

@JonSkeet它可能只是我,但SourceForge Noda時間鏈接是404。 – cadrell0 2012-03-02 19:15:04

1

我要確保我們談論同一個術語。 Thread Safety

一段代碼是線程安全,如果它僅僅操縱共享數據結構中,保證在同一時間安全執行多個線程的方式進行。要做出線程安全的數據結構

看你的方法,它不會是線程安全的唯一方法是,如果你改變一個類的成員或參數在未來的各種策略。

由於這些方法是靜態的,你不能改變你線程安全的方面的成員。

如果您正在更改進入方法的對象,則可能會違反下一個線程安全性。

由於在你的代碼中,你並沒有改變你在那條路徑上很好的變量。你也可以根據你使用的類型來判斷。由於字符串是immutable,它們始終是線程安全的。由於DateTime是線程安全的struct