2009-11-16 5 views
0

Я работаю над повторной записью существующего программного обеспечения Java в .NET. В какой-то момент, решение Java считывает метку времени в начале строки, просто так:Анализ времени от начала строки в C#

SimpleDateFormat dateFormat = new SimpleDateFormat(timeFormat); 
dateFormat.setLenient(false); 

try 
{ 
    timeStamp = dateFormat.parse(line); 
} 
catch (ParseException e) 
{ 
    //... 
} 

Теперь я пытаюсь сделать то же самое в C#:

DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo(); 
dateTimeFormatInfo.FullDateTimePattern = format; 

try 
{ 
    timeStamp = DateTime.Parse(line, dateTimeFormatInfo); 
} 
catch (FormatException ex) 
{ 
    //... 
} 

Оба языка работают пока я не добавлю случайный текст после отметки времени в строке. Java просто проигнорирует его, но C# не позволит ничего другого после текста метки времени в строке.

Так что Java хорошо разбирается "01/01/01 01: 01: 01,001 Hello World!" как временная метка, C# нет, потому что «Hello World!» не указывается в строке формата.

Однако, поскольку я не могу сделать какое-либо утверждение о том, что может произойти после метки времени внутри моих строк, я не могу включить его в строку формата.

Любые идеи?

Заранее спасибо.

+0

Вы уверены, что формат даты всегда будет таким же, как в файле? Просто возьмите первые N символов строки и проанализируйте это. –

+0

Я могу гарантировать, что формат даты будет таким же, да, но ваше решение не учитывает форматы даты, такие как «1 мая 2009 года». Длина может сильно различаться. – Callash

+0

Не ответ на ваш вопрос, но если возможно, вы должны использовать 'DateTime.TryParse', а не' try ... DateTime.Parse ... catch'. http://msdn.microsoft.com/en-us/library/system.datetime.tryparse.aspx – LukeH

ответ

1

Если вы знаете, в каком формате будет находиться ваша дата, и в контексте, в котором он хранится, это преимущество.

Например, если бы вы знали, что вы хранили вчерашние журналы или что-то вроде этого:

DateTime yesterday = DateTime.Today.AddDays(-1); 
timestamp = DateTime.Parse(
    line.SubString(0, line.IndexOf(yesterday.Year.ToString()) + 4)); 

редактировать: Есть ли что-нибудь ограничивающая текст после даты (даже пробел)?

Если есть, то вы могли бы сделать что-то вроде этого:

private static DateTime GetDate(string line) 
{ 
    int index = 0; 
    DateTime theDate; 
    string s = line; 

    while(!DateTime.TryParse(s, out theDate)) 
    { 
     index = line.IndexOf(" ", index); 
     s = line.Substring(0, index); 
    } 

    return theDate; 
} 

Примечания: Это будет не в состоянии получить время, если есть текст после даты (как это будет в состоянии разобрать дату без время успешно при поиске). Вы можете исправить это, получив индекс пробелов, начинающийся в конце строки, и перемещение назад. Я оставлю это вам.

+0

У меня нет, к сожалению. Шаблон формата времени задается конфигурацией, но дата может быть что угодно, вчера, месяц назад, год назад. – Callash

0

Похоже, что .Net будет анализировать всю строку, и вы не контролируете всю строку. Я бы сказал, что используйте TryParse(), и если он терпит неудачу, удалите самое правильное слово из вашей строки и повторите попытку. Я не знаком с Java, но может сделать это под обложками.

2

Попробуйте это:

Dictionary<string, string> tests = new Dictionary<string,string>() 
{ 
    { "yy/MM/dd HH:mm:ss,fff", "01/01/01 01:01:01,001 Hello World!"}, 
    { "yyyyMMddHHmmssfff", "2009111615413829403 Hello World!"}, 
    { "d.M.yyyy H:m:s,fff", "8.10.2009 8:17:26,338 Hello World!" } 
}; 

foreach(KeyValuePair<string, string> test in tests) 
{ 
    string pattern = test.Key; 
    string format = test.Value; 

    DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo(); 
    dateTimeFormatInfo.FullDateTimePattern = pattern; 

    Console.WriteLine("{0} - {1}", pattern, format); 
    DateTime timeStamp = DateTime.MinValue; 
    if (pattern.Contains(' ')) // approach 1: split and conquer 
    { 
     format = String.Join(" ", format 
      .Split(" ".ToCharArray()) 
      .Take(pattern.Count(c => c == ' ') + 1)); 
    } 
    else 
    { 
     format = format.Substring(0, pattern.Length); 
    } 


    if (!DateTime.TryParseExact(
     format, pattern, dateTimeFormatInfo, 
     DateTimeStyles.AllowWhiteSpaces, out timeStamp)) 
    { 
     Console.WriteLine("\tSomething sad happened"); 
    } 
    else 
    { 
     Console.WriteLine("\t{0}", timeStamp.ToString(pattern)); 
    } 
} 
Console.Read(); 

Примечание Я не использую DateTime.Parse, так как он генерирует исключение, если строка не является допустимым DateTime отформатированной строки.

UPDATE 1: обработка Лучше вход, а не ожидать пробелов, но использует длина последовательности

UPDATE 2: Два предыдущих подхода объединены в этот код; Я знаю об использовании одного d в тест # 2, но я не думаю, что мы сможем что-то сделать.

+0

Как добраться, но если я вижу это правильно, это предполагает, что после отметки времени всегда есть пробел. Одна строка, с которой я столкнулся, будет выглядеть так: «2009111615413829403», который является «yyyyMMddHHmmssfff», за которым следует двузначный код ошибки. – Callash

+0

Все еще не так, так как ваше решение ожидает, что шаблон времени и отметка времени будут иметь одинаковую длину. Моим шаблоном может быть «d.M.yyyy H: m: s, fff» (длина 18), а отметка времени для разбора может быть «8.10.2009 8: 17: 26,338» (длина 21). – Callash

+0

Вы правы; этот шаблон всегда действителен? –