Как обрабатывать расплывчатые даты в .Net - PullRequest
27 голосов
/ 27 июля 2011

У меня есть система, которая берет информацию из внешнего источника, а затем сохраняет ее для последующего отображения.

Одним из элементов данных является дата. В исходной системе у них есть концепция нечеткой даты, то есть не точная для определенного дня или иногда не для месяца. Поэтому я получаю даты в формате:

dd/mm/yyyy
mm/yyyy
yyyy

Я могу проанализировать их для объектов DateTime и поработать с ними, но при рендеринге позже мне понадобится определить точность даты, так как при анализе "2010" будет получена дата "01.01.2010". Я хочу показать только год, поэтому нужно знать, насколько он точен.

Я придумал небольшой класс, чтобы разобраться с этим:

public class FuzzyDate
{
    public DateTime Date { get; set; }
    public DateType Type { get; set; }
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}

Это сделает работу за меня, и я могу что-то сделать для анализа, но я чувствую, что это, вероятно, довольно распространенная проблема, и, вероятно, существует более чистое решение.

Есть ли что-то встроенное в .Net для этого? Я взглянул на культуру, но это не совсем правильно.

Любая помощь будет оценена.

Ответы [ 8 ]

14 голосов
/ 27 июля 2011

Чтобы ответить на ваш вопрос: в .NET ничего не встроено, чтобы справиться с этим изящно.

Ваше решение действительно так же, как и все, что я видел. Возможно, вы захотите приукрасить свой класс переопределениями для метода ToString (), который будет правильно отображать вашу дату на основе DateType.

Вот пара других тем, которые пытаются решить этот вопрос:

Удачи!

6 голосов
/ 27 июля 2011

Если ваш тип данных всегда будет обрабатывать определенные периоды времени (т. Е. 1972 год - это определенный период времени, но 4 июля не является конкретным), вы можете сохранить свои данные как время начала и промежуток времени.

  • Если ваша дата была "1972", начальная дата будет 19720101, а промежуток времени будет 366 дней.
  • Если ваша дата была "07/1972", начальная датабудет 19720701, а промежуток времени будет 31 день.
  • Если ваша дата была "04/07/1972", дата начала будет 19720704, а промежуток времени будет 1 день.

Вот возможная реализация:

public struct VagueDate
{
    DateTime start, end;

    public DateTime Start { get { return start; } }
    public DateTime End { get { return end; } }
    public TimeSpan Span { get { return end - start; } }

    public VagueDate(string Date)
    {
        if (DateTime.TryParseExact(Date, "yyyy", null, 0, out start))
            end = start.AddYears(1);
        else if (DateTime.TryParseExact(Date, "MM/yyyy", null, 0, out start))
            end = start.AddMonths(1);
        else if (DateTime.TryParseExact(Date, "dd/MM/yyyy", null, 0, out start))
            end = start.AddDays(1);
        else
            throw new ArgumentException("Invalid format", "Date");
    }

    public override string ToString()
    {
        return Start.ToString("dd/MM/yyyy") + " plus " + Span.TotalDays + " days";
    }
}
6 голосов
/ 27 июля 2011

Когда я начал читать вашу проблему, я быстро пришел к выводу, что ответ заключается в реализации вашего собственного класса FuzzyDate. И вот, это именно то, что вы сделали.

Я могу представить, что вы можете добавить к этому функциональность с течением времени (например, сравнения, учитывающие DateType).

Я не верю, что есть что-то, что по сути поможет вам в .NET Framework, поэтому я думаю, что вы поступаете правильно.

3 голосов
/ 27 июля 2011

Я думаю, что вы идете по правильному маршруту.Не существует понятия «нечеткой» даты или частичной даты, вам нужно будет создать свою собственную.

Скорее всего, вам понадобятся дополнительные методы конструктора, например

public FuzzyDate(int year)
{
   Date = new DateTime(year,1,1); // 1 Jan yy
   Type = DateType.Year;
}

public FuzzyDate(int year, int month)
{
   Date = new DateTime(year, month, 1); // 1 mm yy
   Type = DateType.MonthYear;
}

public FuzzyDate(int year, int month, int day)
{
   Date = new DateTime(year, month, day); // dd mm yy
   Type = DateType.DayMonthYear;
}

Надеюсь, это поможетКевин

1 голос
/ 27 июля 2011

Мне кажется, что ваш подход правильный.Это правда, что .NET DateTime поддерживает несколько форматов, но я предполагаю, что, учитывая, что все они поддерживаются с понятием шагов (наносекунд), они будут связаны с конкретной датой и временем.

0 голосов
/ 27 июля 2011

Вы можете создать свою собственную структуру (определяемый пользователем тип) на основе даты и времени, которая позволила бы 00 для месяца и 00 для дня ... А затем также реализовать icomparable, чтобы вы могли выполнять математические операции / сравнения.1001 *

http://msdn.microsoft.com/en-us/library/k69kzbs1%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/system.icomparable.aspx

0 голосов
/ 27 июля 2011

Насколько я знаю, для этого нет ничего встроенного в .NET, я бы выбрал решение, основанное на значениях Nullable, что-то типа этого.

0 голосов
/ 27 июля 2011

Одна вещь, которую я бы сделал по-другому, - это использовать нулевые значения (или использовать -1 для нулевой семантики) для месяца и дня, чтобы указать, какие данные были собраны.Тогда у меня будет фабричный метод, который будет принимать параметр DateType и возвращать DateTime.Этот метод генерировал бы исключение, если бы был доступен только год, а клиентский код пытался создать DateType.DayMonthYear.

public class FuzzyDate
{
    int _year;
    int? _month;
    int? _day;

    public DateTime Date { get; set; }
    public DateType Type { get; set; }

    public DateTime GetDateTime(DateType dateType) { // ...
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}

Это может показаться слишком сложным, но подход явно сохранит исходные данныеи представляют «поддельные» объекты DateTime только по запросу.Если бы вы сохранили внутренний объект DateTime вместе с перечислением DateType, вы бы потеряли некоторое разрешение.

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