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