2014-10-06 7 views
0

Update Мое решение:Преобразовать необычную строку DateTime ж/из Еогеасп

var rowsToAdd = (from t in dtEntry.AsEnumerable().Cast<DataRow>() 
       let startDate = (
       t.Field<string>("StartDate").Length > 0) 
        ? DateTime.Parse(t.Field<string>("StartDate").Split(new Char [] {'('})[0], CultureInfo.InvariantCulture) 
        : DateTime.Today.AddMonths(-3) 
       where startDate > filterDate 
       select t); 

Оригинал Вопрос: Я получаю строку DateTime из внешнего API, который выглядит следующим образом:

10/14/2014 8:30 AM (America/Los Angeles)

У меня есть все данные в datatable, называемый dtEntry, который я использую ниже.

Ни одна из встроенных функций преобразования C# DateTime не работает. Все они приводят к форматированию исключений. Кто-нибудь знает, как я могу это сделать? Другая проблема заключается в том, что я использую LINQ (см. Ниже).

DataRow[] rows = (from t in dtEntry.AsEnumerable().Cast<DataRow>() 
         let startDate = (
         t.Field<string>("StartDate").Length > 0) 
          ? DateTime.Parse(t.Field<string>("StartDate")) 
          : DateTime.Today.AddMonths(-3) 
         where startDate > filterDate 
         select t).ToArray();          

Любые идеи? У меня есть тернарный оператор, потому что мне нужно также обрабатывать пустые строки.

+4

Нет ничего встроенного в .NET, чтобы разобрать это. Вы либо должны предварительно проанализировать это, и сохранить дату UTC, либо разделить строку на две части. В первой половине даты/времени (например, '' 10/14/2014 8:30 AM '') вы можете разобрать обычным образом. Во-вторых, вам придется проанализировать смещение, с помощью которого вы можете сделать результат первого анализа в формате UTC. –

+0

Также, чтобы исключить исключения, вы можете использовать TryParse вместо Parse. Это, по крайней мере, позволит вам справиться с ошибкой лучше. http://msdn.microsoft.com/en-us/library/system.datetime.tryparse(v=vs.110).aspx – tdbeckett

+0

Я не понимаю, как вы разбираете "10/14/2014 8:30 (Америка/Лос-Анджелес) "* с foreach * ... Не могли бы вы показать образец? –

ответ

4

Вы можете разделить вашу строку на основе пространства, а затем Take(3) элементы из массива результата, Join их обратно с помощью string.Join, а затем использовать DateTime.ParseExact или DateTime.TryParseExact как:

string str = "10/14/2014 8:30 AM (America/Los Angeles)"; 
string newStr = string.Join(" ", str.Split().Take(3)); 

DateTime parsingDateTime; 
if (!DateTime.TryParseExact(newStr, "M/d/yyyy h:mm tt", CultureInfo.InvariantCulture, DateTimeStyles.None, 
    out parsingDateTime)) 
{ 
    //invalid datetime 
} 

EDIT: Вы должны игнорировать (America/Los Angeles) часть string, в противном случае нет возможности для синтаксического анализа с использованием такой строки. Вы можете find TimeZone for Region, а затем создать для этого параметра DateTime. См. Следующее: Get timezone by Country and Region

+2

Очевидно, что дополнительный придаток предназначен для передачи информации о часовом поясе. Вы предлагаете игнорировать его. Это кажется неправильным. – DonBoitnott

+1

@DonBoitnott, тогда нет возможности разобрать дату в такой строке. Я отредактировал свой ответ, чтобы предложить OP, чтобы найти TimeZone. – CriketerOnSO

+0

@CriketerOnSO, хотя я искал решение с использованием LINQ (по моему коду), я действительно использовал это решение: разбор строки времени и использование CultureInfo для ее поиска вместо этого, поэтому я принимаю это как ответ. Спасибо за вашу помощь. – funkhouserben

2

Принятый ответ не учитывает часть часового пояса. Мое предположение - это часовой пояс, который является стандартным идентификатором часового пояса, который можно перевести с Unicode.org site. И исходя от этого другого SO Answer (.NET TimeZoneInfo from Olson time zone) который обеспечивает вспомогательный метод с сайта Unicode.org, вы можете разобрать время апи в свое время:

string apiTime = "10/14/2014 8:30 AM (America/Los Angeles)"; 

int timeZoneStart = apiTime.IndexOf('('); 

string timeZonePart = apiTime.Substring(timeZoneStart) 
    .Replace("(", string.Empty) // remove parenthesis 
    .Replace(")", string.Empty) // remove parenthesis 
    .Trim() // clear any other whitespace 
    .Replace(" ", "_"); // standard tz uses underscores for spaces 
    // (America/Los Angeles) will become America/Los_Angeles 

string datePart = apiTime.Substring(0, timeZoneStart).Trim(); 

DateTime apiDate = DateTime.Parse(datePart); 

TimeZoneInfo tzi = OlsonTimeZoneToTimeZoneInfo(timeZonePart); 

DateTime apiDateTimeConverted = TimeZoneInfo.ConvertTime(apiDate, tzi); 

выше метод, OlsonTimeZoneToTimeZoneInfo, это от SO ответить связан выше.

+0

спасибо за это. Я не думаю, что понимал CultureInfo.InvariantCulture - я посмотрел, и теперь я вижу, что вы говорите. Я не уверен, добавлю ли я это, но это, вероятно, будет хорошей идеей. В моем случае я знаю, что мой код всегда будет работать в одном и том же часовом поясе - и мне действительно нужна только часть дня datetime. Но это полезно. – funkhouserben

+0

@OregonAppDev - даже если вам нужна только часть дня, день в вашем часовом поясе может отличаться от того, где api отправил дату. Просто то, что нужно знать. –