2013-04-01 80 views
-2

我遇到DOS日期格式的問題。我需要轉換:轉換日期到DOS日期

 
From: 
     29th June of 2011 
To: 
     16093 

我知道16093是正確的結果,但我怎麼能得到這個結果呢?


我可以在DOS日整型值轉換爲一個公認DateTime但不知道如何扭轉這一進程。這是我該怎麼辦,從DOS日期轉換爲DateTime

var number = 16093; 

var year = (number >> 9) + 1980; 
var month = (number & 0x01e0) >> 5; 
var day = number & 0x1F; 
var date = new DateTime((int)year, (int)month, (int)day); 

這工作。現在我需要扭轉它。

+1

你試過_anything_? –

+1

什麼是DOS日期格式? –

+0

來源說:'2011年6月29日'是'16093'? –

回答

5

讓我來教你如何釣魚,而在這個過程中解決您的問題。

  1. 我們有什麼?

    A DateTime表示日期/時間組合的.NET對象。

    DateTime dateTime = new DateTime(2011, 6, 29); 
    
  2. 我們想要什麼?

    根據規範的A DOS date/time,但只有16位日期組件。時間組件被忽略。

  3. 我們需要什麼?

    自1980年以來的月份日期,月份數量和年份。讓我們將它們作爲無符號整數並確保它們處於正確範圍內。

    uint day = (uint)dateTime.Day;    // Between 1 and 31 
    uint month = (uint)dateTime.Month;   // Between 1 and 12 
    uint years = (uint)(dateTime.Year - 1980); // From 1980 
    

    請注意,今年有7位,所以它可以代表從1980年到2107年。任何超出該範圍的內容都是無效的。由於years是無符號的,因此它不能表示負值。但是像1970年(減去1980年)的價值將會是4294967286,所以它也超出了範圍。

    if (years > 127) 
        throw new ArgumentOutOfRangeException("Cannot represent the year."); 
    
  4. 我們如何結合呢?

    我們需要將所有值轉移到生成的整數中的適當位置。

    以全零整數開始。我們只需要低16位,但爲了方便起見,我們將在這裏使用uint

    uint dosDateTime = 0; 
    

    該規範列出了每個值開始位的位索引。但由於我們忽略了時間部分(16個最低有效位),我們需要從所有這些值中減去16。

    從第16位開始的天。我們將它左移16-16個位置(即不移位),並且我們可以對這些位進行或運算。

    dosDateTime |= day << (16 - 16); 
    

    月在21位(負16)啓動,並且在幾年位25.

    dosDateTime |= minutes << (21 - 16); 
    dosDateTime |= years << (25 - 16); 
    

    然後把它變成一個無符號的16位整數。它不會溢出。

    ushort result = unchecked((ushort)dosDateTime); 
    
  5. 我們怎麼把它放在一起?

    全部放在一起作爲一個擴展的方法:

    public static class DateTimeExtensions 
    { 
        public static ushort ToDosDateTime(this DateTime dateTime) 
        { 
         uint day = (uint)dateTime.Day;    // Between 1 and 31 
         uint month = (uint)dateTime.Month;   // Between 1 and 12 
         uint years = (uint)(dateTime.Year - 1980); // From 1980 
    
         if (years > 127) 
          throw new ArgumentOutOfRangeException("Cannot represent the year."); 
    
         uint dosDateTime = 0; 
         dosDateTime |= day << (16 - 16); 
         dosDateTime |= month << (21 - 16); 
         dosDateTime |= years << (25 - 16); 
    
         return unchecked((ushort)dosDateTime); 
        } 
    } 
    

    當然,你可以把它寫更簡潔,但是這清楚地表明這是怎麼回事。編譯器會優化許多常量。

  6. 測試它

    你應該寫一些單元測試,看看你的代碼工作正常。但是,這種快速測試驗證的基本思想:

    static void Main(string[] args) 
    { 
        DateTime dateTime = new DateTime(2011, 6, 29); 
        ushort dosDateTime = dateTime.ToDosDateTime(); 
        Console.WriteLine(dosDateTime);  // Prints: 16093 
        Console.ReadLine(); 
    } 
    
+0

wowwwwwwwwwww! +1! –

+0

他所需要的只是對面,dosdate到正常的日期! –

+1

@AppDeveloper他說:「我需要轉換:FROM:2011年6月29日至:16093.我可以將int值轉換爲公認的DateTime,但似乎無法逆轉該過程。」所以,不,他需要正常的日期/時間到DOS日期。 – Virtlink

0

這應該工作正常:

private static DateTime DosDateToDateTime(ushort dosdate) 
{ 
    return new DateTime((dosdate >> 9) + 1980, (dosdate >> 5) & 0xF, dosdate & 0x1F); 
}