2013-04-01 2 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

какой источник говорит: '29 июня 2011'' '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

то, что ему нужно было просто напротив, доздать до нормального дня! –

+1

@AppDeveloper Он говорит: «Мне нужно преобразовать: FROM: 29 июня 2011 г. TO: 16093. Я могу преобразовать значение int в распознанное DateTime, но, похоже, не может изменить процесс». Итак, нет, ему нужна нормальная дата/время до даты DOS. – Virtlink

1

Не похоже, что .Net framework содержит метод только для этого, но knowing the dos time format, с некоторым смещением бит, вы можете написать свой собственный конвертер.

0

это должно отлично работает:

private static DateTime DosDateToDateTime(ushort dosdate) 
{ 
    return new DateTime((dosdate >> 9) + 1980, (dosdate >> 5) & 0xF, dosdate & 0x1F); 
} 
Смежные вопросы