¿Por qué no hay un verdadero tipo de datos "solo de fecha"?

24

Estoy tan ridículamente frustrado por tener que usar los valores de DateTime para conjuntos de datos que realmente son "solo un día". Los cumpleaños son el ejemplo más común, pero esto aparece en las aplicaciones comerciales todo el tiempo.

Me he acostumbrado a configurar la parte Hora de los registros "solo de fecha" en "mediodía" (lo que evita que la fecha cambie sin importar la zona horaria). Esto parece un truco, y siempre encuentro errores de desarrolladores junior que se tropiezan con este problema.

El tiempo siempre es relativo a un punto fijo. 4PM son 4 horas después del meridiano, o mediodía. El punto más alto del sol en tránsito es observable y nos permite establecer un sistema de coordenadas. 3 horas antes del mediodía (Ante Meridian), 2 horas después del mediodía, 1441899402938 milisegundos desde el 1 de enero de 1970. Para las personas criadas en un mundo cartesiano, esta es una segunda naturaleza.

Pero nuestro calendario es anterior a Descartes. Mi argumento es que se considera más propiamente como una enumeración sobre la cual se aplica una función de módulo. El lunes sigue al domingo, y así sucesivamente hasta llegar al hecho de que el domingo sigue al sábado. No hay positivo ni negativo, es un módulo o valor absoluto.

Del mismo modo con años repitiendo. Cada 365 días (más o menos) hay varios días especiales para mí: cumpleaños, aniversarios, cumpleaños de niños, etc. etc. Las aplicaciones de programación comercial abundan con ejemplos de reuniones cada siete días, el primer martes del mes, etc. Simplemente porque PODEMOS mapear esto en un número de coma flotante, y en verdad mapearlo en dicho número resuelve MUCHOS problemas que son realmente difíciles a la antigua usanza, pero eso no significa que sea la única forma de hacerlo.

El conocimiento y la comprensión de la naturaleza de "clavija cuadrada en un agujero redondo" del uso de DateTimes para almacenar fechas lo convierten en un mejor programador en mi opinión.

¿Existe algún valor en una aplicación explícitamente pensada como una aplicación de programación para definir una clase de fecha, o es "establecer todo el tiempo al mediodía" el mejor enfoque? ¿Qué problemas puede haber con el uso de DateTime y la configuración del componente Time en Noon? ¿Se puede explicar el cambio de zona horaria en este enfoque? He usado MomentJS, pero creo que es solo una mejor clase de fecha.

Michael Blackburn
fuente
77
Esta es una pregunta bastante interesante, creo. Tomemos el ejemplo del cumpleaños, solo tiene sentido en humanos, estoy viviendo en un lugar y todos se despiertan al mismo tiempo, más o menos. tan pronto como necesites expresarlo matemáticamente se vuelve muy complejo. Lo mismo con cosas como las horas de inicio / finalización del turno de trabajo, etc.no son 'horas' son 'horas del día en la zona horaria en la que está trabajando'
Ewan
3
NodaTime (una biblioteca de C # para fecha y hora) tiene un tipo de fechas.
CodesInChaos
55
Almacene sus horarios como UTC, sin problemas de fecha, sin problemas de zona horaria.
Loren Pechtel
3
"Pero Dios, esto parece un truco, y siempre encuentro errores de desarrolladores junior que se tropiezan con este problema". - ¿Por qué no creas tu propia clase DateOnly o lo que sea y lo llamas día?
Brandin
55
@MichaelBlackburn lo digo en serio. Su explicación suena exactamente la situación para un tipo de datos propio que hace cumplir la regla de negocio (solo fecha, por ejemplo, puede almacenarlo como "Fecha y hora" internamente con la parte de tiempo establecida al mediodía), pero luego solo expone las partes que desea (mes , día, etc. año / sin año).
Brandin

Respuestas:

15

En primer lugar, eliminemos una cosa: los cumpleaños son una cosa, las fechas de nacimiento son otra. Un cumpleaños es un tipo de datos exótico porque carece no solo de componentes de horas, minutos, etc., sino que también carece del componente de año. Si realmente desea lidiar con los cumpleaños, le recomendaría inventar su propio tipo de datos que no contenga más que un número de mes y un número de día, y que no esté relacionado con ninguno de los tipos de datos de fecha y hora incorporados.

Por otro lado, si también desea realizar un seguimiento del año de nacimiento, lo que tiene no son cumpleaños, sino fechas de nacimiento . Entonces, la pregunta ahora es por qué no hay un tipo de datos solo de fecha, para que pueda representar convenientemente las fechas de nacimiento, y en cambio los idiomas populares parecen obligarlo a usar algún tipo que también incluya un componente de tiempo.

Permítanme mencionar brevemente que no es cierto que todos los lenguajes de programación solo ofrezcan tipos de datos temporales que incluyan un componente de tiempo. Me he encontrado con tipos de datos solo de fecha en RDBMS y en sus dialectos SQL correspondientes. Pero eso es irrelevante: el hecho de que estos tipos de datos existan no significa que sean buenos, y los RDBMS tienen una larga historia de confusión de almacenamiento con representación.

Comprenderá por qué es una mala idea tener esos tipos de datos solo de fecha en el momento en que se da cuenta de que el tiempo es una coordenada. La mayoría de las personas tienen una idea muy vaga de qué hora es, y esta idea contiene nociones culturales arcanas como años, meses y días, sin darse cuenta de que estas nociones son exclusivamente representativas : solo son útiles para representar el tiempo para un humano y para recibir tiempo como entrada de un humano. En cualquier capa debajo del control de la GUI de entrada de tiempo real, el tiempo debe representarse, y generalmente se representa, como una coordenada de tiempo, que es un número único de unidades de tiempo desde cierto origen.

Por ejemplo, en el DateTimetipo de datos de Microsoft Dotnet, la unidad de tiempo es de 100 nanosegundos, y el origen del tiempo es 12:00 de la medianoche, 1 de enero de 0001 CE

Otro ejemplo de una notación arcana, exclusivamente representativa, es la medición de ángulos usando grados, minutos de un grado y segundos de un grado. Por supuesto, para realizar cualquier cálculo útil, debe usar radianes internamente y, si es necesario, convertir hacia y desde grados al interactuar con un usuario humano.

Por lo tanto, no confunda la representación legible por humanos de una medición con la naturaleza real de la medición. Muy a menudo, el método ideal para realizar una medición, que se asemeja más a la naturaleza de la medición, es muy diferente de la representación legible por los humanos de esa medición.

A la luz de todo esto, su solicitud de un tipo de datos temporales que represente solo fechas es similar a una solicitud de un tipo de datos angular que solo sea capaz de representar grados, evitando explícitamente una mayor precisión. Tal tipo de datos sería bastante limitado y, en última instancia, inútil, porque de todos modos tendría que convertirlo hacia y desde radianes para poder hacer algo útil con él.

Su problema con la fecha de nacimiento es que tiene una coordenada de tiempo imprecisa : la persona, por supuesto, nació en un momento específico en el tiempo, pero el hospital no registró la hora y los minutos, o nosotros no. preocuparse por ellos. Entonces, lo que realmente está sucediendo es que su coordenada de fecha y hora de nacimiento tiene un margen de error, una tolerancia o incertidumbre si lo desea, y es mejor tratarlo como tal: póngalo exactamente en el medio del día, y considere una incertidumbre implícita de +12 a 12 horas. Y esa es precisamente la solución a la que ha llegado intuitivamente.

Mike Nakis
fuente
44
Esto no es cierto para los "Días", que son un concepto incluso más antiguo que el Tiempo. Se los considera más propiamente como una enumeración o un módulo. El domingo sigue al lunes, etc. hasta que volvamos al domingo, que sigue al sábado. Es realmente una cosa diferente.
Michael Blackburn
10
Bueno, por supuesto, el hospital anotó la hora de nacimiento, esa es una práctica estándar en la mayoría de los hospitales. Ese no es el problema en absoluto. El problema es que con el propósito de conmemorar eventos (cumpleaños, días festivos, aniversarios, etc.) las personas no usan o desean una resolución que sea más fina que 1 día. Vaya a preguntarle a la primera persona que vea cuando sea su cumpleaños, y le darán un mes y un día, pero nunca una hora y un minuto. Además: utilizamos unidades que incluyen escala todo el tiempo: milímetro, kilogramo, megavatio y, de hecho, microfaradios.
Caleb
44
-1: No todos los usos del tiempo representan un solo momento en el tiempo. Un cumpleaños es una idea diferente, representada por un mes y un día en el calendario gregoriano. Tiene sentido preguntar "¿Hoy es el cumpleaños de Kevin?" La respuesta depende de la ubicación. Si estoy en Sydney podría ser mi cumpleaños, pero si estuviera en Honolulu, no lo sería por algunas horas todavía.
Kevin Cline
66
@MikeNakis El resultado serían microamperios, no tonterías. Más importante: cuando usa una fecha en lugar de un segundo o milisegundo, generalmente está hablando de todo el día, un período de tiempo , en lugar de una hora específica, y dependiendo del contexto, puede ser un evento repetitivo.
Caleb
44
El OP hablaba de cumpleaños, que están representados exactamente por java.util.MonthDay. Un cumpleaños no es una medida, es la noción humana de un día que se repite anualmente. Hay muchas ideas humanas del tiempo que no están representadas por un solo punto en el tiempo.
Kevin Cline
9

Las fechas y horas son diferentes según el contexto, y necesita muchos tipos distintos para cubrir todos los casos de uso.

El DateTimetipo presente en muchos idiomas representa un punto preciso en el tiempo ("tiempo instantáneo"). Más allá de esto, tenemos una serie de conceptos relativos o temporales "humanos", como días calendario, fechas recurrentes, meses, años, etc., que en muchos casos son ambiguos y dependen del contexto. Estos tipos no son tan universalmente útiles, pero necesarios en dominios de aplicación específicos como calendarios, herramientas de programación y otras aplicaciones que interactúan con conceptos humanos del tiempo.

Si está escribiendo algo así como una aplicación de calendario, definitivamente se beneficiaría al usar una biblioteca como Joda-time que proporciona un conjunto más rico de tipos de tiempo. Por ejemplo LocalDate, una fecha sin tiempo. Esto tiene una semántica diferente a la ordinaria DateTimecon la parte de tiempo establecida en cero, ya que el DateTimetodavía indica un punto específico en el tiempo (medianoche en una zona horaria específica), mientras que LocalDateindica todo el día y no está vinculado a una zona horaria específica. Esto también significa que no puede traducir directamente uno al otro.

LocalDatees ciertamente más simple que DateTimeporque no tiene que tomar en cuenta las zonas horarias, pero debe tener en cuenta los otros problemas, por ejemplo, que la fecha actual puede retroceder cuando cruza una zona horaria y que el mismo instante en el tiempo puede corresponden a diferentes fechas en diferentes zonas horarias. Si está utilizando fechas locales en aplicaciones web o en red, debe tener mucho cuidado con estos problemas. ¡Eliminar la parte de tiempo de una fecha no resuelve el problema fundamental de las zonas horarias! Y si toma en cuenta las fechas históricas y las diferentes culturas, se vuelve aún más complicado, ya que la misma fecha puede corresponder a instancias muy diferentes en el tiempo, por ejemplo, el calendario juliano versus el gregoriano.

Ahora pregunta por qué los idiomas no tienen algo como LocalDate incorporado . En primer lugar, algunos lenguajes como SQL y Visual Basic tienen un tipo de fecha sin parte de tiempo. Y Java también ha agregado un LocalDateen la versión reciente. Pero otras plataformas como .Net no. Solo los diseñadores de idiomas realmente pueden responder por qué esto no está incluido en la biblioteca estándar, pero supongo que el "tiempo instantáneo" es conceptualmente simple y universalmente útil, mientras que los otros conceptos de tiempo solo son útiles para dominios de aplicación específicos (como calendarios, etc. .). Por lo tanto, tiene sentido dejar que el desarrollador de la aplicación escriba tipos personalizados para manejar los casos de uso más complejos, o dejar que lo maneje una biblioteca de terceros (como Joda-time).

JacquesB
fuente
5

Estoy tan ridículamente frustrado por tener que usar los valores de DateTime para conjuntos de datos que realmente son "solo un día". Los cumpleaños son el ejemplo más común, pero esto aparece en las aplicaciones comerciales todo el tiempo.

Esto probablemente se deba a que el calendario es complicado y se usa de muchas maneras diferentes, por lo que nadie ha podido calcular una clase que sea simple pero lo suficientemente general como para ser útil en muchos campos.

El tipo de fecha que se encuentra comúnmente en los lenguajes de programación se puede usar para fechar con precisión las transacciones en un sistema informático. Es probable que otros casos de uso requieran una biblioteca personalizada.

Aquí hay una breve lista de datos sobre calendarios, que demuestran su complejidad: la mayoría de ellos son históricos, por lo que si restringe su atención a las fechas posteriores al 1.1.1970, esto no lo afectará. Sin embargo, si su solicitud necesita trabajar con fechas que ocurrieron antes de fines del siglo XIX, entonces estos hechos serían importantes. Los posibles casos de uso son bases de datos históricas de todo tipo (libros, genealogía) pero también activos de grandes empresas u organizaciones que todavía están en actividad hoy en día.

Todos estos hechos se citan de las excelentes preguntas frecuentes que se encuentran en la biblioteca de calendario para OCaml escrita por Julien Signolles.

  1. El calendario juliano fue introducido por Julio César en el 45 a. C. Era de uso común hasta el año 1500, cuando los países comenzaron a cambiar al calendario gregoriano (sección 2.2). Sin embargo, algunos países (por ejemplo, Grecia y Rusia) lo usaron en la década de 1900, y la iglesia ortodoxa en Rusia todavía lo usa, al igual que otras iglesias ortodoxas.

  2. El cambio del calendario juliano al gregoriano no se produjo de manera uniforme y, según el año de cambio, se han eliminado de 10 a 13 días. Por ejemplo, en Francia el 9 de diciembre de 1582 fue seguido por el 20 de diciembre de 1582 y en Grecia el 9 de marzo de 1924 fue seguido por el 23 de marzo de 1924.

  3. Incluso en la era moderna, se utilizan muchos calendarios diferentes (gregoriano, ortodoxo, islámico y chino) para citar algunos, que utilizan diferentes formas de calcular años y aniversarios o la fecha de las celebraciones religiosas.

Ahora espera un tipo de fecha incluido con operaciones útiles para operaciones comerciales generales. Supongo que no existen las operaciones comerciales generales. Por ejemplo, en el mundo financiero, necesitamos calcular:

  1. Las fracciones de año (como "6 meses" corresponde a "0.5"), que se utilizan junto con una tasa de interés para calcular el interés real de un préstamo para un plazo determinado. Hay 6 a 10 recetas para calcular estas fracciones, cada una de las cuales difiere en la forma en que manejan la duración de un año bisiesto, la posición del período con respecto al último día de febrero y la duración de un mes.

  2. Fecha límite, cuando calculamos aniversarios, utilizamos un calendario comercial y una regla (elegida de un conjunto de más de 6 reglas diferentes) para cambiar un aniversario de un día festivo a un día hábil.

Para las personas que trabajan en la industria financiera, cualquier tipo de calendario que no implemente todas estas funciones y reglas es inútil. Es probable que muchas otras industrias tengan otros tipos de hábitos y convenciones que requieren cálculos personalizados en el calendario.

¿Existe algún valor en una aplicación explícitamente pensada como una aplicación de programación para definir una clase de fecha, o es "establecer todo el tiempo al mediodía" el mejor enfoque? ¿Qué problemas puede haber con el uso de DateTime y la configuración del componente Time en Noon? ¿Se puede explicar el cambio de zona horaria en este enfoque? He usado MomentJS, pero creo que es solo una mejor clase de fecha.

Si necesita realizar un seguimiento de un solo día calendario, la mejor manera es probablemente usar un número entero grande que represente el día juliano de ese día calendario. Los algoritmos para convertir de ida y vuelta del día juliano al día calendario, que se describe con año, mes y calendario, son ampliamente conocidos y probados exhaustivamente, para que pueda implementarlos fácilmente en su aplicación, y descubrir qué regla es pertinente en su caso para calcular el aniversario de un evento que ocurre en el 29 de febrero.

Michael Le Barbier Grünewald
fuente
2

Creo que Mike Nakis en su respuesta anterior hace un mejor trabajo que yo al explicar cómo el tiempo en general es una coordenada medida absoluta y cualquier otra comunicación, supuesto estado o persistencia de esa coordenada de tiempo es simplemente una representación abstracta de dicha coordenada de tiempo.

Usted habla de tales representaciones cuando se refiere al Día de la Semana como simplemente una especie de módulo de representación de un punto en el tiempo real. En realidad es algo más complicado que eso. Si se le asignó la tarea de escribir una función que devolverá el Día de la semana para un momento determinado, considere la siguiente información que necesitará como entrada para dicho algoritmo. Necesitará el punto en el tiempo, el Calendario, la zona horaria a tener en cuenta (tenga en cuenta que las zonas horarias cambian TODO EL TIEMPO, por lo que debe saber cuándo comenzó esa zona horaria efectiva cuando terminó en coordenadas de tiempo específicas. ¡cambiaron los suyos, por ejemplo!), y si el horario de verano está vigente, esto también cambia con el tiempo. Ahora considere si le dieron una fecha y hora en la zona horaria local,

Puedes ver lo complicada que puede ser esta pregunta aparentemente simple.

Sé el dolor que siente cuando estaba en su lugar en un momento arreglando todos los errores en una aplicación de programación de visitas para un producto que fue escrito por desarrolladores inexpertos. Todo el asunto tuvo que ser desechado.

El tiempo es de hecho una coordenada, pero además de una simple Fecha, considere otros datos sensibles al tiempo que podrían ser necesarios como:

Duración: un lapso de milisegundos que puede ocurrir que significa una longitud o paso del tiempo sin coordenadas de tiempo específicas especificadas. Un caso de uso podría ser,

Como usuario, me gustaría que esta tarea se realizara 15 segundos después de completar el trabajo de medianoche cada dos miércoles.

Intervalo: un rango de tiempo entre dos coordenadas de tiempo específicas. Un caso de uso en el que es posible que desee considerar un intervalo.

Como usuario, necesito ver todos los días del mes totalmente contenidos dentro de un intervalo de tiempo especificado.

Otro punto rápido que quería hacer es que hiciste un comentario sobre los números de punto flotante para los datos basados ​​en el tiempo y no lo aconsejo. La aritmética de punto flotante inevitablemente conduce a errores de redondeo que pueden no proporcionarle una medición tan precisa como sea necesaria para el tiempo.

En conclusión, toda esta información conduce inevitablemente a las siguientes consideraciones de diseño:

  • Deben persistir puntos o rangos específicos en el tiempo en UTC o algún tipo de datos que contenga suficiente información para ser fácilmente abstraído a UTC donde sea necesario
  • La lógica de la aplicación debe escribirse para formatear UTC o un rango de coordenadas UTC en un estado de datos representativos que sea más digerible para el usuario final.
  • Las duraciones importantes deben persistir en milisegundos.
  • Las preferencias locales específicas o del usuario final en la visualización de cualquier dato sobre el tiempo deben mantenerse como datos adicionales y tratarse como una opción de visualización. (Por ejemplo, quiosco A, zona horaria central, formato de hora militar o preferencias del usuario B, hora estándar en la zona horaria de Tel Aviv (GMT + 7: 00), etc.)
  • Evita los números FP
árbol de arce
fuente
1
Nada de esto es "inevitable". Puede ser común para muchas aplicaciones, pero el Gran Colisionador de Hadrones trata eventos en la escala de nanosegundos. Los tiempos del sistema se han movido a microsegundos porque los milisegundos no tienen suficiente precisión. Las aplicaciones de calendario deben tener un concepto de una fecha que ocurre en un día calendario local, independientemente de si se encuentra en la misma zona horaria en la que creó el evento.
Alan Shutko
1
@AlanShutko Y sí, los "datos adicionales" que se necesitan son cosas como la zona horaria local, y Días, y cualquier otra información importante que deba capturarse. Sin embargo, todas estas son solo abstracciones para un solo punto en el tiempo, incluso si el punto en el tiempo no es importante para su algoritmo. En cuanto a la escala de nanosegundos e incluso microsegundos, mi respuesta está más orientada al software web y de tipo LOB. Dudo que el lenguaje de elección de LHC sea C # o Javascript.
maple_shaft
1
Los milisegundos son excelentes para procesos físicos repetibles. Para la actividad humana, a veces la unidad apropiada es días nominales, por ejemplo, si se envía al final del día, estará disponible para su uso en el destino tres días después.
Kevin Cline
En el pasado, he considerado el uso de números de coma flotante de 64 bits para las coordenadas de tiempo y, lo que es más importante, para intervalos de tiempo, ya que le permiten expresar pequeñas cantidades con gran precisión, así como grandes cantidades, donde la pérdida de precisión realmente no importa . (¿Y qué si los Dinosaurios murieron hace 65 millones de años más o menos unos años?) Entonces, ¿por qué dices que deberían evitarse?
Mike Nakis
Mike, creo que su preocupación es que la matemática FP se redondea inevitablemente, ya que se convierte de valores decimales a binarios. Por ejemplo, 0.3 es un decimal repetido cuando se expresa como un número FP binario y, por lo tanto, no se puede representar exactamente. No es que te falta la capacidad, sino que te falta la precisión.
Michael Blackburn
2

En resumen, porque la mayoría de los tipos de tiempo basados ​​en computadora se centran en manejar el problema de hora y zona horaria correctamente.

Hay 2 casos extremos que no se atienden bien con el enfoque habitual. Establecer un punto en el tiempo que esté al otro lado de un cambio de horario de verano utilizando la hora local, que luego se convierte en el UTC por una capa de abstracción inferior, y luego te hace 1 hora más temprano / tarde para tu reunión.

El otro es (según la pregunta) modelar información de fecha arbitraria, como registrar la fecha de nacimiento de una persona. Imagine el caso en el que nacen dos personas al mismo tiempo, una en Nueva Zelanda y la otra en Hawai. La probabilidad es que tengan diferentes fechas de nacimiento en sus pasaportes, y si la persona nacida en Hawai se muda a Nueva Zelanda, se la considerará un día mayor que la persona nacida en Nueva Zelanda, a pesar de haber vivido exactamente el mismo tiempo.

La sugerencia en la pregunta como establecer la fecha para tener una hora del mediodía, UTC funcionará, casi en todas partes. Las compensaciones de UTC varían de -12 a +14, por lo que hay algunos lugares en el Pacífico donde este enfoque fallará. Tiendo a tratar estos tipos de datos como cadenas, en un formato aaaammdd, y si tengo que hacer cálculos de comparación entre dos fechas, esto se puede hacer de forma segura como una comparación de cadenas. Al hacer comparaciones delta (por ejemplo, entre la fecha y ahora, o cuánto tiempo hasta que alcancen la edad X), debe asegurarse de que todas las fechas se creen en el mismo desplazamiento UTC, y luego puede usar las funciones de hora estándar para hacer el trabajo.

Michael Shaw
fuente
3
" Tiendo a tratar estos tipos de datos como cadenas, en un formato aaaammdd, y si tengo que hacer cálculos de comparación entre dos fechas, esto se puede hacer de manera segura como una comparación de cadenas " . Eso suena como un Datetipo de datos, solo se lleva aString
Ross Patterson
Tal como usted dice, es una representación en cadena de una fecha, y a diferencia del póster original, la fecha no cambia al estar en una zona horaria UTC + 13.
Michael Shaw
2

¿Por qué no hay un verdadero tipo de datos "solo de fecha"?

Por las mismas razones, creo, que los valores de DateTime generalmente se especifican en UTC: simplicidad y confiabilidad . El punto de un valor de DateTime es especificar un único punto en el tiempo que no se vea afectado por la zona horaria, el horario de verano, el calendario y otros ajustes locales. Los valores de fecha y hora especifican un instante (hasta el límite de la resolución del tipo), no un período de tiempo o un conjunto de horas. Estas limitaciones permiten comparar los valores de DateTime de una manera confiable, predecible y sin complicaciones.

Intentar especificar una fecha con un valor DateTime es como intentar usar un punto para especificar un área.Puede hacer que eso funcione usando una convención, como "este punto representa el centro de un círculo con un radio de 100 m", pero hay muchos problemas allí: todos deben usar la misma convención, usted necesita escribir un montón de código de soporte para hacer que trabajar con el tipo incorrecto sea menos doloroso, y está prácticamente garantizado que en algún momento necesitará especificar un área que sea más grande o más pequeña que el área convencional. Lo mismo ocurre con las fechas: puede usar 'mediodía' como la hora convencional para especificar fechas, pero luego ingresa a las zonas horarias porque las personas esperan especificar fechas en su hora local en lugar de UTC. E incluso si encuentra una manera satisfactoria de usar un DateTime para especificar una fecha, necesitará más información para saber si es una fecha absoluta o relativa: ¿es el 4 de julio? ¿1776 o cada 4 de julio? ¿Qué pasa si quieres repetir usando algún otro período? Y los calendarios tienen todo tipo de problemas locos: algunos meses son más largos que otros, algunos años son más largos que otros, algunos días son incluso más largos que otros, y algunos calendarios tienen lagunas. No querrá resolver estos problemas solo durante días enteros, porque los mismos problemas surgen por períodos más cortos: probablemente le gustaría poder escribir código que exprese "tome 1 píldora cada 4 horas" tan fácilmente como "el el grupo se reúne cada tercer viernes ".

Entonces, hay muchas complicaciones involucradas al trabajar con fechas. Es relativamente fácil (sin juego de palabras) proporcionar un tipo que especifique un punto en el tiempo y trabajar con él como lo haría con un número, pero es extremadamente difícil proporcionar un tipo que aborde todas las formas en que se usan las fechas.

Como otros han señalado, no son lenguajes y bibliotecas que proporcionan un buen apoyo para las fechas, y es a menudo una buena idea para usarlos dado que es muy difícil conseguir el código de fecha relacionada con la razón.

Caleb
fuente
2
"Es difícil proporcionar un tipo que aborde todas las formas en que se usan las fechas". Es cierto, por eso es una idea horrible tratar de proporcionar un solo tipo para hacerlo todo. Las primeras versiones de Java proporcionaron solo java.util.Date y el resultado fue horrible. Luego agregaron una compleja jerarquía java.util.Calendar y no mejoró mucho.
Kevin Cline
1
@kevincline Totalmente de acuerdo. OP no especificó un idioma, por lo que apuntaba a la generalidad.
Caleb
" Por las mismas razones, creo, que los valores de DateTime generalmente se especifican en UTC " ... Oh, eso sería cierto. Es 2015, y todavía se está escribiendo mucho código utilizando la zona horaria local del autor :-(
Ross Patterson
1
De hecho, me preguntaba por qué no hay una convención generalmente aceptada en torno a las fechas. Su "uso de un punto para representar un área" encapsula perfectamente mi frustración.
Michael Blackburn el
2

¿Por qué no hay un verdadero tipo de datos "solo de fecha"?

Hay muchos tipos de este tipo en varias bibliotecas para varios idiomas. Es casi seguro que haya uno para su idioma actual. El paquete de utilidades Java tenía una API horrible para los cálculos de tiempo, pero la introducción del paquete java.time ha mejorado mucho la vida. Consulte java.time.LocalDate, que contiene un valor año-mes-día, o java.time.MonthDay, que contiene solo un número de mes y día.

Kevin Cline
fuente
1

La manipulación calendárica es uno de los aspectos menos conocidos de la informática. Se han escrito libros completos sobre el tema. @MichealBlackburn tiene toda la razón al solicitar un tipo de datos solo de fecha, uno que no se resuelva hasta un punto en una línea de tiempo, sujeto a reinterpretación. Históricamente, ha habido disputas legítimas sobre el significado de una fecha. Uno no tiene que buscar más allá de la adopción del calendario gregoriano para descubrir cuán complejo puede llegar a ser. Además, los años no siempre han comenzado el 1 de enero, incluso en Europa occidental y sus colonias ( por ejemplo , Gran Bretaña y América británica comenzaron el año el 25 de marzo).

Ross Patterson
fuente
1
Esto es correcto. Las preguntas frecuentes del calendario que cito en mi respuesta son un excelente recurso para descubrir las complejidades y sutilezas de las manipulaciones de clanes
Michael Le Barbier Grünewald
-2

En respuesta a:

Bueno, sinceramente me gustaría saber por qué casi todos los idiomas solo tienen un tipo de datos para esto.

La razón más común podría ser "porque no es necesario". Si desea una fecha y hora que no se preocupe por horas, minutos, segundos, etc., simplemente debe inicializarla así:

date = new DateTime(year, month, day, 0, 0, 0);

Si lo desea, puede extender DateTime usted mismo:

public class Date extends DateTime {
    ...
    public Date(int year, int month, int day) {
        this(year, month, day, 0, 0, 0);
    }
}

Nota: Estoy ignorando intencionalmente la hora y zona horaria predeterminadas. Realmente no importa en qué los configures, siempre que sean los mismos para todos Date. Puede presentar un caso para UTC. Puede presentar un caso para usar la zona horaria en la que se encuentra su servidor; de cualquier manera, no creo que sea importante para representar un valor impreciso comoDate . Lo mismo con el tiempo predeterminado: puede ponerlo en 0, puede hacerlo al mediodía. No importa. Si Facebook me envía una notificación de cumpleaños a las 00:01 pero nací a las 23:59, realmente no me importa, y no me ofende que hayan faltado más de 12 horas.

Lo anterior está en Java, pero funcionaría de manera similar en cualquier lenguaje con una DateTimeherencia y. Java en realidad tiene numerosas formas de resolver esto, y lo anterior está en desuso (quieren que lo uses Calendarahora). Pero, como otros publicados en los comentarios, algunos idiomas realidad hacen proporcionar unaDate clase, presumiblemente por esta razón.

Con toda probabilidad, cada Dateimplementación es probablemente solo un contenedor para el lenguaje DateTimey pone a cero el tiempo. De lo contrario, necesitaría un código duplicado para resolver problemas como la cantidad de días entre dos fechas / fechas y horas, o si dos Dates son iguales (¿Qué pasa con el 29 de febrero y el 1 de marzo?). Ese tipo de cosas generalmente se resuelven en la DateTimeclase. Tiene sentido reutilizar el mismo código para a Date.

Shaz
fuente
44
-1: Use LocalDate si desea solo año + mes + día. Usar DateTime para ese propósito generará errores cuando otro programador vea DateTime y suponga que representa un momento en el tiempo.
Kevin Cline
@kevincline No creo que sea necesario porque esta pregunta no tiene en cuenta el idioma. También creo que es obvio que el uso de código etiquetado como "obsoleto" es un escenario de uso bajo su propio riesgo. Lo que es más importante, solo lo usé como un ejemplo de algo que puede hacer en un escenario en el que un idioma no tiene una clase de tipo LocalDateo Datetiene que 'rodar por su cuenta'.
Shaz
1
Pero "ES ES necesario" para un código claro, conciso y correcto que involucre reglas comerciales sobre el tiempo (en oposición al tiempo físico). si la biblioteca no proporciona tipos por tiempo nominal, será necesario que el programador los invente, y la forma de hacerlo no comienza con "DateTime".
Kevin Cline
@kevincline No veo cómo el código sería menos claro o conciso. ¿Cuál es la diferencia desde el punto de vista de un programador entre new Date(2000, 1, 1);y new Date(2000, 1, 1);? ¿Puedes decir cuál tiene horas, minutos y segundos vacíos debajo? Si le preocupa que aparezcan funciones adicionales (como setMinutes ()), entonces podría tomar la ruta de Dateenvolver en DateTimelugar de heredar de él, y luego solo expondrá setYear, setMonth, setDay, etc. Y ciertamente no es menos correcto que el DateTime de la biblioteca que está utilizando.
Shaz
Mi experiencia es en gran parte C #, que no tiene una construcción análoga a LocalDate. Acabamos de simplemente DateTime y entramos, aparentemente.
Michael Blackburn