Esta es la decimotercera entrega de la serie sobre utilidades para Business Central. En esta ocasión comparto un bloque completo de funciones para calcular diferencias entre fechas y datetimes. Cada función viene con dos sobrecargas: una con un parámetro (compara contra la fecha base 01/01/1900) y otra con dos parámetros (compara entre dos valores concretos).

¡Vamos manos a la obra! 📆


📅 Diferencia entre fechas en días: SubtractTwoDateReturnDays

procedure SubtractTwoDateReturnDays(ValueDate1: Date) ReturnValue: Integer
var
    ValueDate2: Date;
begin
    Clear(ValueDate2);
    ReturnValue := this.SubtractTwoDateReturnDays(ValueDate1, ValueDate2);
end;

procedure SubtractTwoDateReturnDays(ValueDate1: Date; ValueDate2: Date) ReturnValue: Integer
begin
    if ValueDate1 = 0D then
        ValueDate1 := DMY2Date(1, 1, 1900);

    if ValueDate2 = 0D then
        ValueDate2 := DMY2Date(1, 1, 1900);

    ReturnValue := ValueDate1 - ValueDate2;
end;

¿Qué hace esta función?

Devuelve la diferencia en días entre dos fechas como un Integer. Si alguna de las fechas es vacía (0D), se sustituye automáticamente por el 01/01/1900 como valor base.

  • Sobrecarga con 1 parámetro: compara ValueDate1 contra el 01/01/1900.
  • Sobrecarga con 2 parámetros: compara ValueDate1 contra ValueDate2.

📅 Diferencia entre fechas como Date: SubtractTwoDatesReturnAsDate

procedure SubtractTwoDatesReturnAsDate(ValueDate1: Date) ReturnValue: Date
var
    ValueDate2: Date;
begin
    Clear(ValueDate2);
    ReturnValue := this.SubtractTwoDatesReturnAsDate(ValueDate1, ValueDate2);
end;

procedure SubtractTwoDatesReturnAsDate(ValueDate1: Date; ValueDate2: Date) ReturnValue: Date
var
    DaysDiff: Integer;
begin
    DaysDiff := this.SubtractTwoDateReturnDays(ValueDate1, ValueDate2);
    ReturnValue := DMY2Date(1, 1, 1900) + DaysDiff;
end;

¿Qué hace esta función?

Similar a la anterior, pero el resultado se devuelve como un tipo Date en lugar de Integer. Internamente calcula los días de diferencia y los suma a la fecha base 01/01/1900, generando así un valor Date que representa la duración.

Útil cuando se necesita mostrar la diferencia como fecha en un campo o página, o cuando se quiere operar sobre ella con funciones de fecha de AL.


⏱ Diferencia entre DateTimes en milisegundos: SubtractTwoDateTimesReturnMilliseconds

procedure SubtractTwoDateTimesReturnMilliseconds(ValueDateTime1: DateTime) ReturnValue: BigInteger
var
    ValueDateTime2: DateTime;
begin
    Clear(ValueDateTime2);
    ReturnValue := this.SubtractTwoDateTimesReturnMilliseconds(ValueDateTime1, ValueDateTime2);
end;

procedure SubtractTwoDateTimesReturnMilliseconds(ValueDateTime1: DateTime; ValueDateTime2: DateTime) ReturnValue: BigInteger
var
    DurationDiff: Duration;
begin
    Clear(ReturnValue);

    if ValueDateTime1 = 0DT then
        ValueDateTime1 := CreateDateTime(DMY2Date(1, 1, 1900), 000000T);

    if ValueDateTime2 = 0DT then
        ValueDateTime2 := CreateDateTime(DMY2Date(1, 1, 1900), 000000T);

    DurationDiff := ValueDateTime1 - ValueDateTime2;

    ReturnValue := (DurationDiff div 1); // Duration en milisegundos
end;

¿Qué hace esta función?

Calcula la diferencia entre dos valores DateTime y la devuelve en milisegundos como BigInteger. El tipo Duration en AL es precisamente la diferencia entre dos DateTime, expresada en milisegundos.

  • Los valores vacíos (0DT) se sustituyen por el DateTime base: 01/01/1900 00:00:00.
  • El resultado puede ser negativo si ValueDateTime1 es anterior a ValueDateTime2.

⏱ Diferencia entre DateTimes como DateTime: SubtractTwoDateTimesReturnAsDateTimeFromMilliseconds

procedure SubtractTwoDateTimesReturnAsDateTimeFromMilliseconds(ValueDateTime1: DateTime) ReturnValue: DateTime
var
    ValueDateTime2: DateTime;
begin
    Clear(ValueDateTime2);
    ReturnValue := this.SubtractTwoDateTimesReturnAsDateTimeFromMilliseconds(ValueDateTime1, ValueDateTime2);
end;

procedure SubtractTwoDateTimesReturnAsDateTimeFromMilliseconds(ValueDateTime1: DateTime; ValueDateTime2: DateTime) ReturnValue: DateTime
var
    MillisecondsDiff: BigInteger;
    BaseDateTime: DateTime;
begin
    Clear(ReturnValue);
    MillisecondsDiff := this.SubtractTwoDateTimesReturnMilliseconds(ValueDateTime1, ValueDateTime2);

    BaseDateTime := CreateDateTime(DMY2Date(1, 1, 1900), 000000T);

    ReturnValue := (BaseDateTime + (MillisecondsDiff * 1));
end;

¿Qué hace esta función?

Es la variante que devuelve la diferencia en milisegundos representada de nuevo como DateTime. Calcula los milisegundos de diferencia con la función anterior y los suma al DateTime base (01/01/1900 00:00:00), obteniendo un DateTime que "representa" esa duración.

Especialmente útil cuando necesitas almacenar o mostrar la duración en un campo de tipo DateTime.


💡 Beneficios y aplicaciones prácticas

Este conjunto de funciones es ideal en escenarios como:

  • Calcular la antigüedad de un registro (días desde su creación).
  • Medir el tiempo transcurrido entre dos eventos en un proceso.
  • Calcular duraciones de órdenes de producción, albaranes o documentos.
  • Integraciones que necesitan enviar diferencias de tiempo en milisegundos.
  • Mostrar la diferencia de fechas en campos calculados de páginas o informes.

El diseño con dos sobrecargas por función aporta flexibilidad: si solo tienes una fecha de referencia, llamas con un parámetro; si tienes las dos, las pasas ambas.


Conclusión

En esta decimotercera entrega de la serie Utils, presento un bloque completo de funciones para calcular diferencias entre fechas y datetimes en AL. Cada función viene en dos variantes para adaptarse a distintos casos de uso, devolviendo el resultado como entero, como fecha o como DateTime según la necesidad.

Para seguir todos los posts de esta serie, puedes encontrarlos bajo la etiqueta #UtilsBc.

Si quieres ver el código completo, está en GitHub.

¡Nos vemos en la próxima!