Подтвердить что ты не робот

Как работать с неопределенными датами в .Net

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

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

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 для этого? Я взглянул на культуру, но это было не совсем правильно.

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

4b9b3361

Ответ 1

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

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

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

Удачи!

Ответ 2

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

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

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

Ответ 3

Если ваш тип данных будет всегда обрабатывать определенные периоды времени (то есть 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";
    }
}

Ответ 4

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

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

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;
}

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

Ответ 5

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

Ответ 6

Одна вещь, которую я хотел бы сделать по-другому, - использовать значения с нулевым значением (или использовать -1 для нулевой семантики) в течение месяца и дня, чтобы указать, какие данные были собраны. Тогда у меня был бы метод factory, который принял бы параметр 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, вы потеряете некоторое разрешение.

Ответ 7

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

public class FuzzyDate
{
    private int Year;
    private int? Month;
    private int? Day;

    public FuzzyDate(int Year, int? Month, int? Day)
    {
        this.Year = Year;
        this.Month = Month;
        this.Day = Day;
    }

    public DateType DateType
    {
        get
        {
            if(Day.HasValue && Month.HasValue)
            {
                return DateType.DayMonthYear;
            }
            else if(Month.HasValue)
            {
                return DateType.MonthYear;
            }
            else
            {
                return DateType.Year;
            }
        }
    }

    public DateTime Date
    {
        get
        {
            return new DateTime(Year, Month.GetValueOrDefault(1), Day.GetValueOrDefault(1));
        }
    }
}

public enum DateType
{
    DayMonthYear,
    MonthYear,
    Year
}

Ответ 8

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

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