¿Debo hacer un objeto DateRange?


Algunos de mis objetos de dominio contienen intervalos de fechas como un par de propiedades de fecha de inicio y de finalización:

public class Period {
  public DateTime EffectiveDate { get; set; }
  public DateTime ThroughDate { get; set; }
}

public class Timeline {
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

Y me encuentro con mucho de esto:

abstract public int Foo(DateTime startDate, DateTime endDate);
abstract public decimal Bar(DateTime startDate, DateTime endDate);
abstract public ICollection<C5.Rec<DateTime, DateTime>> FooBar(DateTime startDate, DateTime endDate);

El último me hizo preguntarme ... ¿Debo implementar una clase DateRange? No tengo conocimiento de uno en la BCL.

En mi experiencia, hacer que la jerarquía de objetos sea más profunda a menudo complica las cosas. Estos objetos se envían a los informes RDLC mostrados por el control ReportViewer, pero eso es secundario. Voy a doblar la vista a la modelo en lugar de viceversa. Sin embargo, no estamos atados a los nombres de las propiedades, y estaríamos dispuestos a comprometernos con algo como:

public class DateRange {
  public DateTime StartDate { get; set; }
  public DateTime EndDate { get; set; }
}

Period p = new Period();
DateTime t = p.EffectiveDateRange.StartDate;

Un beneficio de una clase DateRange sería la validación centralizada de la fecha de finalización que viene después de la fecha de inicio, y simplificará mis firmas de método:

abstract public int Foo(DateRange dateRange);
abstract public decimal Bar(DateRange dateRange);
abstract public ICollection<DateRange> FooBar(DateRange dateRange);

Simplemente no estoy seguro de que una clase DateRange no me meta en más problemas que su valor. Opiniones?

Pregunta secundaria: ¿Me perdí una clase de tupla genérica de propósito general en ¿el BCL en alguna parte? Sé que hay algunos muy específicos flotando en varios espacios de nombres. Contaminar mis firmas de métodos de dominio público con tipos C5 se siente muy, muy sucio.

Author: Viktor Dahl, 2009-12-04

5 answers

No, no te perdiste una clase de propósito general.

Tengo un tipo Range en MiscUtil que puede interesarle - y ciertamente hace que la manipulación sea simple DateTime. Refiriéndose a la respuesta de Marc, no puedo recordar si esto es una estructura o una clase - usted sería bienvenido a cambiarlo, por supuesto.

Es agradable y fácil de pasar, debido a las travesuras genéricas de Marc (suponiendo que esté utilizando. NET 3.5, al menos, es factible con 2.0, pero no es compatible con el momento);

Range<DateTime> range = 19.June(1976).To(DateTime.Today);

foreach (DateTime date in range.Step(1.Days())
{
    // I was alive in this day
}

(Eso también es usar un montón de métodos de extensión, más útiles para pruebas que para producción.)

Para abordar el otro punto en la respuesta de Marc, Noda Time ciertamente podrá expresar el concepto de una fecha más apropiadamente que la API.NET, pero no tenemos nada como un rango en este momento... Sin embargo, es una buena idea: he agregado una solicitud de característica .

 36
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-04 08:11:24

En.NET 4.0 o superior se agregó el tipo de tupla para manejar múltiples valores.

Con el tipo de tupla puede definir su propia combinación de valores sobre la marcha. Su problema es muy común y es similar a cuando una función quiere devolver varios valores. Anteriormente tenía que usar variables o crear una nueva clase solo para la respuesta de la función.

Tuple<DateTime, DateTime> dateRange =
    new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now);

Cualquiera que sea la ruta que tome, creo que definitivamente está tomando el enfoque correcto. Estás dando verdadero significado a lo que dos citas emparejadas lo son. Eso es código auto-documentable y de la mejor manera, justo en la estructura del código.

 8
Author: Timothy Gonzalez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-28 22:21:27

Si trabajas mucho con fechas, sí - un rango puede ser útil. Este es en realidad uno de esos casos tan raros en los que debería probablemente escribirlo como struct (inmutable). Tenga en cuenta, sin embargo, que "Tiempo Noda" probablemente le dará todo esto y más (cuando esté completo). He hecho software de programación antes; tenía un par de tales estructuras (para trabajos ligeramente diferentes).

Tenga en cuenta que no hay una construcción BCL útil para esto.

También-piensa en todo lo maravilloso métodos (y posiblemente operadores) que puede centralizar cuando tiene un rango; "contiene" (de una fecha y hora? de otro rango? ¿incluyendo / excluyendo límites?), "intersects", offset-by (a timespan), etc. Un definido caso para tener un tipo para manejarlo. Tenga en cuenta que en el nivel OR, esto es más fácil si su OR admite valores compuestos - creo que NHibernate lo hace, y posiblemente EF 4.0.

 5
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-04 07:59:50

No conozco ninguna clase.NET nativa de naturaleza DateRange. El más cercano es probablemente DateTime + TimeSpan o DateTime / DateTime combinación.

Creo que lo que quieres es bastante sólido.

 0
Author: o.k.w,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-04 08:01:02

Como Mark y Jon ya mencionaron, crearía esto como un tipo de valor, que es inmutable. Yo optaría por implementarlo como una estructura, e implementar las interfaces IEquatable e IComparable.

Al usar un OR como NHibernate, podrá almacenar el tipo de valor dentro de una tabla que representa una entidad.

 0
Author: Frederik Gheysels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-04 08:12:14