Лучший способ обработки различных форматов DateTime в C# - PullRequest
0 голосов
/ 26 апреля 2020

Я беру данные из листа Excel, и значения DateTime варьируются в зависимости от следующих перестановок:

(d/M/yyyy HHmm)   1/2/2020 2359
(dd/M/yyyy HHmm)  25/2/2020 2359
(d/MM/yyyy HHmm)  5/12/2020 2359
(dd/MM/yyyy HHmm) 24/12/2020 2359

Для других сценариев ios, где они меняют день и месяц, я бы просто хочу поймать исключение на этом.

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

Есть ли универсальное c решение, которое может справиться с вышеуказанными ситуациями?

В настоящее время я использую следующее:

public DateTime ParseDateAndTime(string dateValue, int? timeValue)
{
    var combinedDate = $"{dateValue} {(timeValue ?? 0) / 100}:{(timeValue ?? 0) % 100}";

    return DateTime.ParseExact(combinedDate, "d/M/yyyy H:m", CultureInfo.InvariantCulture);
}

PS Данные получены из Excel и имеют заданный формат (дд / мм / гггг ЧЧмм). Но пользователи могут ввести один ди git день / месяц, и я хотел бы справиться с этим. Все остальные форматы, кроме указанных, я бы хотел отловить как исключения ...

Ответы [ 4 ]

1 голос
/ 26 апреля 2020

Как я вижу, у вас дата в виде строки, но ваше значение времени может быть нулевым. Поэтому я бы предложил разделить ваш анализ в 2 этапа: дата и время. Другое дело, что я бы возвратил его как объект datetime, поэтому я могу использовать его так, как я хочу вместо использования ParseExact. Таким образом, если ваше время пустое или имеет проблему, вы все равно будете анализировать дату.

Вы также можете, конечно, если дата не разбирается, добавляя условие и возвращая дату по умолчанию вместо, через исключение или что-то еще else.

Просто базовый c пример, что-то вроде этого:

public DateTime ParseDateAndTime(string dateValue, int? timeValue)
{
    var time = $"{(timeValue ?? 0) / 100}:{(timeValue ?? 0) % 100}";
    var isTimeParsed = TimeSpan.TryParse(time, out var timeParsed);
    DateTime.TryParse(dateValue, out var dateParsed);
    if (isTimeParsed)
    {
        dateParsed = dateParsed.Add(timeParsed);
    }
    return dateParsed;
}

В случае, если вам нужно вызвать исключение, вы делаете что-то вроде:

var isDateParsed = DateTime.TryParse(dateValue, out var dateParsed);
if (!isDateParsed)
{
    throw new Exception("date is not parsable");
}

Если вам нужно представить флаг, я бы предложил создать собственный объект и расширить описанный выше метод, например:

public MyDateTimeObject ParseDateAndTime(string dateValue, int? timeValue)
{
    var result = new MyDateTimeObject();
    var time = $"{(timeValue ?? 0) / 100}:{(timeValue ?? 0) % 100}";
    var isTimeParsed = TimeSpan.TryParse(time, out var timeParsed);
    var isDateParsed = DateTime.TryParse(dateValue, out var dateParsed);
    if (!isDateParsed)
    {
        result.ParsingIssue = true;
        return result;
        //Or
        //throw new Exception("date is not parsable");
    }
    if (isTimeParsed)
    {
        result.ParsedDatetime = dateParsed.Add(timeParsed);
    }
    return result;
}

И ваш класс

public class MyDateTimeObject
{
    public DateTime ParsedDatetime { get; set; }
    public bool ParsingIssue { get; set; }
}
1 голос
/ 26 апреля 2020

Работает:

var dates = new[]
{
    "1/2/2020 2359",
    "25/2/2020 2359",
    "5/12/2020 2359",
    "24/12/2020 2359"
};

foreach (var date in dates)
{
    Console.WriteLine(ParseDateAndTime(date));
}

public DateTime ParseDateAndTime(string dateValue)
{
    return DateTime.ParseExact(dateValue, "d/M/yyyy HHmm", CultureInfo.InvariantCulture);
}
0 голосов
/ 26 апреля 2020

Если вы пытаетесь получить дату из Excel, и данные сохраняются как Дата в Excel, попробуйте получить ее как объект DateTime, используя Range.Value.

Если DateTime.ParseExact() работает, просто используйте его.

Если он хранится в виде строки, а функция DateTime.ParseExact() не работает работать, однако, я советую вам написать функцию самостоятельно для анализа строки.

Например:

 public static DateTime getDate(string date)
        {

            string[] splitedDate = date.Split('/');

            int day;
            if (int.TryParse(splitedDate[0], out day)) ;
            else
            {
                throw new ArgumentException();
            }
            int month;
            if (int.TryParse(splitedDate[1], out month)) ;
            else
            {
                throw new ArgumentException();
            }
            int year;
            if (int.TryParse(splitedDate[2], out year)) ;
            else
            {
                throw new ArgumentException();
            }

            return new DateTime(year, month, day);
        }

Хотя может быть и лучшее решение.

0 голосов
/ 26 апреля 2020

Я предполагаю, что вы не знаете формат c для каждого значения DateTime при чтении из Excel, правильно? Как вы получаете данные? Например, если вы напрямую открываете файл Excel с помощью Interop или чего-то еще, вы можете попробовать прочитать CellFormat указанной ячейки c. Наверняка для этого необходимо, чтобы формат DateTime был правильно установлен в файле Excel / листе Excel.

Или вы получаете DateValues ​​в виде простого списка без ссылки на файл Excel / лист Excel? Затем вы можете попробовать использовать TryParseExact, используя разные форматы даты, и посмотреть, какие совпадения, так как TryParseExact возвращает логическое значение в качестве результата. Tricky может быть датой, такой как 12/12/2020 - 12 действительна как для месяца, так и для дня. Поэтому необходимо как-то получить формат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...