2011-02-15 44 views
2

背景Java和C#之間的日期時間轉換能否引入錯誤?

我正在使用Apache的NMS庫與ActiveMq交談。每個發送的消息都由生產者加上時間標記,我通過從DateTime.UtcNow減去時間戳來查看消息延遲,我期望看到0-100ms的延遲,但是我看到報告的延遲在-1000和1000ms之間。很明顯,負面的延遲是沒有意義的,所以我最初懷疑係統時鐘不同步,但是現在我已經獨立地確認它們是正確的並且在彼此的20ms內。

更多的背景

Measuring broadcast message latency using system clock, good idea?

問題

我現在相信的差異可能是由於日期.Net和Java之間的處理方式。

  • 是從Java轉換到/從.Net時代有損?
  • 轉換能否解釋我觀察到的大負時間跨度?
  • 還有什麼可以解釋時差嗎?

MessageProducer.cs - 生產者設置NMSTimestamp

activeMessage.NMSTimestamp = DateTime.UtcNow; 

ActiveMqMessage.cs - NMSTimestamp轉換成Java的時間和存儲上的消息

... 
public DateTime NMSTimestamp 
{ 
    get { return DateUtils.ToDateTime(Timestamp); } 
    set 
    { 
     Timestamp = DateUtils.ToJavaTimeUtc(value); 
     if(timeToLive.TotalMilliseconds > 0) 
     { 
      Expiration = Timestamp + (long) timeToLive.TotalMilliseconds; 
     } 
    } 
} 
... 

留言.cs - 時間戳保持導線格式化的日期,編組設置直接

// ActiveMqMessage extends Message 
... 
public long Timestamp 
{ 
    get { return timestamp; } 
    set { this.timestamp = value; } 
} 
... 

DateUtils.cs此值的消息 - 用於執行轉換

namespace Apache.NMS.Util 
{ 
    public class DateUtils 
    { 
     /// <summary> 
     /// The start of the Windows epoch 
     /// </summary> 
     public static readonly DateTime windowsEpoch = new DateTime(1601, 1, 1, 0, 0, 0, 0); 
     /// <summary> 
     /// The start of the Java epoch 
     /// </summary> 
     public static readonly DateTime javaEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0); 

     /// <summary> 
     /// The difference between the Windows epoch and the Java epoch 
     /// in milliseconds. 
     /// </summary> 
     public static readonly long epochDiff; /* = 1164447360000L; */ 

     static DateUtils() 
     { 
      epochDiff = (javaEpoch.ToFileTimeUtc() - windowsEpoch.ToFileTimeUtc()) 
          /TimeSpan.TicksPerMillisecond; 
     } 

     public static long ToJavaTime(DateTime dateTime) 
     { 
      return (dateTime.ToFileTime()/TimeSpan.TicksPerMillisecond) - epochDiff; 
     } 

     public static DateTime ToDateTime(long javaTime) 
     { 
      return DateTime.FromFileTime((javaTime + epochDiff) * TimeSpan.TicksPerMillisecond); 
     } 

     public static long ToJavaTimeUtc(DateTime dateTime) 
     { 
      return (dateTime.ToFileTimeUtc()/TimeSpan.TicksPerMillisecond) - epochDiff; 
     } 

     public static DateTime ToDateTimeUtc(long javaTime) 
     { 
      return DateTime.FromFileTimeUtc((javaTime + epochDiff) * TimeSpan.TicksPerMillisecond); 
     } 
    } 
} 

我的代碼計算延遲如下

var latency = (DateTime.UtcNow - msg.NMSTimestamp).TotalMilliseconds; 
+0

如何日期時間在電報格式表示的?實際上是否包含毫秒?通用的日期時間格式,通過電線在'秒'處停止並添加偏移量,但不加毫秒。 – 2011-02-15 11:35:58

+0

@Marvin - 它只是作爲一個長期傳輸,所有的轉換都在 – chillitom 2011-02-15 11:40:42

回答

3

是的,從Java時間轉換到/從Java時間轉換是有損的。這是由於Java時間不像Windows時間那麼精確。不同時間格式之間的轉換保證精確至毫秒而不丟失。不過,更精確的Windows Ticks將會丟失。

NMS DateTime實用程序轉換功能正常工作。您遇到的錯誤來自您的延遲計算代碼。您正在使用var類型,並且這是您的錯誤進入的位置。TotalMilliseconds返回一個值,並且這將創建舍入錯誤。解決方法是將值截斷爲整個毫秒,而不是部分毫秒,因爲如上所述,這是有損的。請嘗試使用下面的代碼與一個強類型來計算時延:

long latency = System.Math.floor((DateTime.UtcNow - msg.NMSTimestamp).TotalMilliseconds);