delphi - tipos - ¿Qué estructura de datos se recomienda para múltiples calendarios, fechas y duraciones?
porque usamos el calendario gregoriano (2)
Si está escribiendo uno propio, como supongo que tiene la intención, haría una clase que contiene un TDateTime y otros campos, y lo basaría en la funcionalidad en la muy bien escrita extensión mxDateTime para Python, que es muy fácil código C legible, de código abierto, que podría usar para extraer la lógica del calendario gregoriano que va a necesitar.
Dentro de ciertos límites, TDateTime siempre tiene la razón. Su valor de época (0) es el 30 de diciembre de 1899 a la medianoche. A partir de ahí, puede calcular otros números del día juliano. Admite valores negativos y, por lo tanto, admitirá más de 400 años. Creo que comenzarán a tener correcciones, en el momento de las últimas reformas del calendario gregoriano. Si va desde el viernes, 15 de octubre de 1582, y calcula su número de día juliano, y las reformas antes y después, debe poder hacer todo lo que necesite. Tenga en cuenta que la hora del día corre "hacia atrás" antes de 1899, pero que esto es solo un problema en las cabezas humanas, la computadora será precisa y calculará el número de minutos y segundos, hasta el límite del punto flotante de doble precisión matemáticas para ti Quédate con TDateTime como tu base.
Encontré un código BorlandPascal / TurboPascal muy antiguo que maneja una amplia gama de fechas aquí .
Si necesita manejar árabe, judío y otros calendarios, una vez más, lo remito a Python como una gran fuente de ejemplos de trabajo. No solo la extensión mxdatetime, sino cosas como esta .
Para la persistencia de la base de datos, es posible que desee basar el almacenamiento de la fecha en torno a los números del día juliano, y su tiempo en segundos tipo C desde la medianoche, si la resolución máxima que necesita es de 1 segundo.
Aquí hay un fragmento con el que comenzaría y completar el código en:
TCalendarDisplaySubtype = ( cdsGregorian,cdsHebrew,cdsArabic,cdsAztec,
cdsValveSoftwareCompany, cdsWhoTheHeckKnows );
TDateInformation = class
private
FBaseDateTime:TDateTime;
FYear,FMonth,FDay:Integer; // if -1 then not calculated yet.
FCalendarDisplaySubtype:TCalendarDisplaySubtype;
public
function SetByDateInCE(Y,M,D,h,m,s:Integer):Boolean;
function GetAsDateInCE(var Y,M,D,h,m,s:Integer):Boolean;
function DisplayStr:String;
function SetByDateInJewishCalendar( ... );
property BaseDateTime:TDateTime read FDateTime write FDateTime;
property JulianDayNumber:Integer read GetJulianDayNumber write SetJulianDayNumber;
property CalendarDisplaySubType:TCalendarDisplaySubtype;
end;
No veo ninguna razón para ALMACENAR tanto el número del día juliano como el TDateTime, simplemente use una constante, reste / agregue del valor Trunc (FBaseDateTime), y devuelva eso, en las funciones GetJulianDayNumber, SetJulianDayNumber. Puede valer la pena tener campos donde se calcula el año, mes, día, para el calendario dado, una vez, y almacenarlos, haciendo que la visualización como cadena sea mucho más simple y rápida.
Actualización: Parece que eres mejor en ER Modeling que yo, así que si publicaste ese diagrama, lo votaría mejor, y eso sería todo. En cuanto a mí, estaría almacenando tres campos; Un campo de fecha y hora que se normaliza según los estándares del calendario moderno, un campo de texto (formulario libre) que contiene la fecha académica original en cualquier forma, y algunos otros campos, que son claves extranjeras de tabla de búsqueda de subtipo, para ayudarme a organizar y buscar fechas por la fecha y el subtipo. Eso sería IT para mí.
Tengo un requisito para almacenar fechas y duraciones que surgen de múltiples calendarios diferentes. En particular, necesito almacenar fechas que:
- Extender el cambio a los calendarios gregorianos en diferentes países en diferentes momentos
- Cubra un período histórico de al menos 500 años
- Trate con múltiples tipos de calendario: lunar, solar, chino, financiero, cristiano, UTC, musulmán.
- Haga frente al cambio, en el Reino Unido, del fin de año del 31 de marzo al 31 de diciembre, y cambios comparables en otros países.
También necesito almacenar duraciones que he definido como la diferencia entre dos marcas de tiempo (fecha y hora). Esto implica la necesidad de poder almacenar una fecha "cero", por lo que puedo almacenar duraciones de, digamos, tres horas y media; o 10 minutos.
Tengo detalles de los cálculos necesarios. La marca de tiempo de Firebird se basa en una función de fecha que comienza el 1 de enero de 100 CE, por lo que no se puede usar para duraciones en la forma en que necesito registrarlas. Además, este tipo de datos está preparado (como la mayoría de las funciones de marca de tiempo) para registrar el número de días desde una fecha base; no está preparado para registrar las fechas del calendario.
¿Alguien podría sugerir?
- Una estructura de datos para almacenar fechas y duraciones que cumplen con los requisitos anteriores O
- Una referencia a dicha estructura de datos O
- Ofrecer pautas para abordar la estructuración de dicho almacenamiento O
- Cualquier punto que pueda ayudarme a una solución.
EDITAR:
@Warren P ha proporcionado un excelente trabajo en sus respuestas. Obviamente no he explicado lo que estoy buscando con claridad, ya que su trabajo se concentra en los cálculos y en cómo calcularlos. Todo lo valioso y útil, pero no lo que pretendía que transmitiera mi pregunta.
Tengo detalles de todos los cálculos necesarios para convertir varias representaciones de fechas, y tengo una idea bastante buena de cómo implementarlas (utilizando elementos como sugiere Warren). Sin embargo, mi requisito es ALMACENAR fechas que cumplan con los diversos criterios enumerados anteriormente. Ejemplo: fecha para ser almacenado - ''Tercer 13 de junio Carlos II''. Estoy tratando de determinar una estructura apropiada dentro de la cual almacenar esas fechas.
EDITAR:
He modificado mi esquema propuesto. He enumerado los atributos en cada tabla, y he definido las tablas y atributos por ejemplos, que figuran en la tercera sección del cuadro de entidad. He usado el ejemplo dado en esta pregunta y respuesta en mi definición por ejemplo, y he modificado el ejemplo en mi pregunta para corresponder. Aunque he probado mi esquema al describir el ejemplo de otra persona, este esquema puede ser aún demasiado complicado; sobre analizado; se pierde una simplificación obvia y puede resultar muy difícil de implementar (de hecho, puede ser completamente erróneo). Cualquier comentario o sugerencia sería bienvenido.
Solo una respuesta parcial pero una pieza importante.
Como va a almacenar fechas en un rango muy amplio en el que pasaron muchas cosas con los calendarios, debe adaptarse a esos cambios.
La base de datos TZ de la base de datos de la zona horaria y el contenedor Delphi TZDB alrededor de la base de datos TZ serán de gran ayuda.
Tiene una base de datos con reglas sobre cómo se comportan históricamente las zonas horarias.
Sé que se basan en los esquemas de calendario actuales, y primero debe convertir a UTC.
Necesita diseñar algo similar para los otros esquemas de calendario que desea admitir.
Editar:
El esquema que usaría sería así:
- encuentre maneras para que todos sus calendarios se conviertan a / desde UTC
- almacenar el tipo de calendario
- almacene las fechas en su formato original y el origen de la fecha (en caso de que su fuente se estropee y necesite volver a calcular).
- utilice las conversiones de UTC para pasar de su original a UTC a los tipos de calendario en su UI
--jeroen