2012-06-28 2 views
2

Я пытаюсь читать даты в следующем формате, используя одну строку формата:DateTime.ParseExact для нетрадиционного лет

"1000.12.31" 
"999.12.31" 
"99.12.31" 

Они будут соответствовать датам в годы 1000 AD, 999 AD и 99 ОБЪЯВЛЕНИЕ.

Я попытался следующие строки формата:

yyyy.M.d. Это терпит неудачу на годы 999 и 99.

yy.M.d. Это не подходит для 1000 и 999. Он также интерпретирует 99 как 1999.

Я собираюсь прибегнуть к разбору его вручную (это достаточно просто для этого), но мне любопытно, если что-то подобное возможно даже с DateTime.ParseExact , или, возможно, с помощью другого встроенного метода?

+0

Не работает ли 'y.M.d'? – leppie

+0

«99.12.31» является двусмысленным для человека. * Никто не пойдет «ах, это, конечно, 99 год в царствование Маркуса Ульпиуса Нервы Траяна Августа». Каждый выбор 1999 года. Машина не улучшается. –

+0

@leppie: нет, такой же результат, как 'yy.M.d' iirc. @Hans Мне, в этом контексте, это не двусмысленно. Я знаю, что я всегда хочу 99, чтобы быть 99, а не 1999, я просто не могу это указать. Как дни и месяцы, они могут быть двусмысленными (1/2, это первая или вторая половина?), Но если вы знаете, чего ожидать, вы можете указать это в строке формата. – Bubblewrap

ответ

2

Это тривиально для разбора вручную; Я не думаю, что это стоит усилий, пытаясь адаптировать его для работы с DateTime.ParseExact.

string str = "99.12.31"; 
int[] parts = str.Split('.').Select(int.Parse).ToArray(); 
DateTime date = new DateTime(parts[0], parts[1], parts[2]); 
2

Я думаю, что самый простой способ - взять существующую строку, наклеить несколько нулей перед годом и использовать существующий DateTime.ParseExact.

Однако вы его реализуете, я бы сделал небольшую ручную настройку струн и делал тяжелый подъем с помощью DateTime.ParseExact.

static DateTime ParseExactYear(string input) 
{ 
    switch (input.IndexOf('.')) 
    { 
     case 1: input = "000" + input; break; 
     case 2: input = "00" + input; break; 
     case 3: input = "0" + input; break; 
    } 

    return DateTime.ParseExact(input, "yyyy.M.d", null); 
} 

Debug.WriteLine(ParseExactYear("1000.12.31")); 
Debug.WriteLine(ParseExactYear("999.12.31")); 
Debug.WriteLine(ParseExactYear("99.12.31")); 
Debug.WriteLine(ParseExactYear("9.12.31")); 

Debug.WriteLine(ParseExactYear("1000.1.1")); 
Debug.WriteLine(ParseExactYear("999.1.1")); 
Debug.WriteLine(ParseExactYear("99.1.1")); 
Debug.WriteLine(ParseExactYear("9.1.1")); 

Output: 
12/31/1000 12:00:00 AM 
12/31/0999 12:00:00 AM 
12/31/0099 12:00:00 AM 
12/31/0009 12:00:00 AM 
1/1/1000 12:00:00 AM 
1/1/0999 12:00:00 AM 
1/1/0099 12:00:00 AM 
1/1/0009 12:00:00 AM 
+0

И тогда он взрывается на '' 1.1.1 '': * ( – leppie

+0

Предполагается, что месяцы и дни всегда представлены в 2-х цифрах. – Matthew

+0

@Matthew: И игнорирование одиночных цифр тоже; p – leppie

2

Он интерпретирует 99 как 1999 из-за DateTimeFormatInfo значений текущей культуры. Если вы хотите изменить поведение синтаксического анализа необходимо изменить DateTimeFormatInfo:

string eg = "9.1.2"; 
DateTime dt; 

var fi = new System.Globalization.DateTimeFormatInfo(); 
fi.Calendar = (System.Globalization.Calendar)fi.Calendar.Clone(); 
fi.Calendar.TwoDigitYearMax = 99; 
fi.ShortDatePattern = "y.M.d"; 
bool b = DateTime.TryParse(eg, fi, System.Globalization.DateTimeStyles.None, out dt); 

Новые экземпляры DateTimeFormatInfo одни и те же Calendar объекта; вы должны указать Clone, если хотите настроить определенные экземпляры.

Смежные вопросы