2014-04-03 47 views
0

我需要將數十億的DateTimes從UTC轉換爲EDT。什麼是TimeZoneInfo.ConvertTime的更快選擇?

TimeZoneInfo.ConvertTime非常方便,但非常非常慢。

我比較簡單的時間跨度減法。請參閱下面的SSCCE。

如果您註釋掉OPTION 1或OPTION 2(如代碼所示),您將看到VASTLY不同的運行時間。

我想要的功能,但需要更高的速度有沒有辦法做到這一點?

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Windows.Forms; 
using System.IO; 
using System.Globalization; 


namespace BinTest2 
{ 
    public partial class Form1 : Form 
    { 

     static TimeZoneInfo edtZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 
     static TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); 
     static TimeZoneInfo utcZone = TimeZoneInfo.FindSystemTimeZoneById("UTC"); 
     public static CultureInfo ci = CultureInfo.InvariantCulture; 

     private void button5_Click(object sender, EventArgs e) 
     { 
      Stopwatch sw = new Stopwatch(); 
      sw.Start(); 

      DateTime DT = new DateTime(2013,01,01); 

      DateTime TDT; 
      TimeSpan TS = new TimeSpan(4,0,0); 
      for (int i = 0; i < 100000000; i++) 
      { 
       //TDT = DT - TS; //OPTION 1 
       TDT = TimeZoneInfo.ConvertTime(DT, utcZone, edtZone); //OPTION 2 
      } 

      sw.Stop(); 

      label1.Text = "Time taken: " + sw.ElapsedMilliseconds ; 


     } 
    } 
} 
+1

難道你不能做一個幫助你的方法嗎?這對我來說似乎是兩全其美。 –

+0

問題在於不同日期的時區更改。 TimeZoneInfo處理所有這一切 – ManInMoon

+2

由於這兩個選項做了不同的事情(如您所指出的,選項1沒有考慮DST),所以說選項1是「更快」並不公平。(您指出,選項1不考慮DST) –

回答

2

在考慮性能之前,請考慮正確性。

你的兩個例子給出了不同的結果。

當夏時制正在運行時,東部時間比UTC晚4h; 5h時不。你簡單的減法沒有考慮到這一點(事實上,你指定的樣本日期會給出錯誤的結果 - 差異是2013年1月1日的5小時)。

此外,您還需要警惕自制的基準測試,這可能會給出不切實際的結果,尤其是如果您的應用不是在發佈模式下構建的。

如果你想不考慮夏令時的結果,你可以使用:

edtZone.BaseUtcOffset 

,而不是硬連線:

new TimeSpan(4,0,0) 

使你的代碼更易讀。

+0

我知道 - 這只是一個比較。因此我說我想要TimeZoneInfo的功能! – ManInMoon

+0

同意......你能預先計算出它們的速度,並將EST值緩存在某處嗎?如果你需要這是可靠的正確的,我不會推出自己的。如果沒關係,它「可能」是正確的,那麼是的,沒什麼大不了的。而且我知道你說過你只是想要EST,但如果你從這方面擴展,你就會給自己一個受傷的世界。我幾個月前看過這個,它讓我害怕從不停地滾動我自己的時區轉換器:http://youtu.be/HIToWgDVg54 – Rikon

0

根據您要處理的日期範圍,您可以使用字典來完成。這樣,第二次你做,它會更快。當然,這隻有在你連續進行有限的幾天時纔有效。如果你有一個更大的範圍,你每天做一次(難以想象的數十億人 - 地球只有這麼老:),那麼這不會很好。另外,你必須牢記記憶。

如果您實際上每小時(或分鐘和更細)地執行DT,那麼您將需要使用涵蓋小時和分鐘的整數索引,以便您可以正確處理夏令時更改。

public partial class Form1 : Form 
{ 
    Dictionary<DateTime,TimeSpan> lut = new Dictionary<DateTime, TimeSpan>(); 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    static TimeZoneInfo edtZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); 
    static TimeZoneInfo gmtZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time"); 
    static TimeZoneInfo utcZone = TimeZoneInfo.FindSystemTimeZoneById("UTC"); 
    public static CultureInfo ci = CultureInfo.InvariantCulture; 

    private void button5_Click(object sender, EventArgs e) 
    { 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 

     DateTime DT = new DateTime(2013, 01, 01); 

     DateTime TDT; 
     TimeSpan TS = new TimeSpan(5, 0, 0); 
     for (int i = 0; i < 100000000; i++) 
     { 
      if (!lut.ContainsKey(DT)) 
      { 
       lut[DT] = DT - TimeZoneInfo.ConvertTime(DT, utcZone, edtZone);      
      } 

      TDT = DT - lut[DT]; 

     } 

     sw.Stop(); 

     label1.Text = "Time taken: " + sw.ElapsedMilliseconds; 


    } 
} 
+0

我不能使用字典,因爲每個TimeStamp都是唯一的,因爲我需要ms。 – ManInMoon

+0

你的工作範圍是什麼?您仍然可以使用查找表,因爲夏令時僅在小時或半小時內發生變化。 (除非有人想糾正我)。假設您需要精確到0CE和3000CE之間的分鐘,您可以創建一個定製的uint散列,其中包括年份爲12位,月份爲4,日期爲5,小時爲5,分鐘爲6。你只會使用其中的一小部分。 – mike1952

0

一般來說,我認爲你是在嘗試微觀優化。你在真的會看到一個明顯的差異,在這裏幾毫秒的改善?不見得。

此外,TimeZoneInfo轉換可能不會像直接TimeSpan減法一樣快,但正如其他人指出的那樣 - 它們不會做同樣的事情。請在the timezone tag wiki中閱讀「Time Zone!= Offset」。

如果您正在尋找TimeZoneInfo的替代方案,我建議您評估DateTimeZone課程Noda Time。 Jon Skeet是主要作者,他當然專注於性能調優。我不是100%確定如果它是更快TimeZoneInfo,但我知道它肯定更實用,更準確。

此外,您可能已經意識到這一點,但值得指出。 "GMT Standard Time"不是GMT的時區。這是「都柏林,愛丁堡,里斯本,倫敦」的Windows時區ID。它在夏季的GMT(UTC + 00:00)和冬季的BST(UTC + 01:00)之間交替。同樣,Windows時區標識符"Eastern Standard Time"表示EST(UTC-05:00)和EDT(UTC-04:00)。這就是爲什麼時區轉換比簡單的減法更復雜的原因。

+0

>你真的會看到一個明顯的差異,在這裏提高几毫秒? 該OP提到他需要轉換_billions_日期。 1億毫秒超過11天。所以看來OP可能會注意到11天的表現改善 –