Compartir vía


Variantes locales, fijas y UTC de las funciones de hora actual

Cuando trabaja con Power Query en herramientas como Excel y Power BI, controlar los valores de fecha y hora con precisión es esencial, especialmente cuando las transformaciones de datos dependen de la hora actual. Power Query ofrece varias funciones para recuperar la fecha y hora actuales:

En este artículo se exploran las diferencias entre estas funciones y se aclara cuándo y por qué usar cada una. Además, resalta un detalle crítico pero a menudo pasado por alto. Power Query Online siempre devuelve la hora UTC incluso cuando se usa una función etiquetada como "Local". Comprender estos matices puede ayudarle a evitar resultados inesperados, especialmente al compilar informes sensibles al tiempo o automatizar las actualizaciones de datos en aplicaciones como el servicio Power BI o Power Apps.

Diferencias entre funciones

Cada una de las funciones de hora actual tiene diferencias importantes. Estas funciones varían en términos de reconocimiento de zona horaria, volatilidad (si el valor cambia cuando se llama varias veces en la misma consulta) y cómo se comportan en diferentes entornos (escritorio frente a en línea). La tabla siguiente contiene un desglose de cada función.

Función Devoluciones Volatilidad Comportamiento del escritorio Comportamiento en línea Caso de uso típico
DateTime.LocalNow Un datetime que representa la hora local actual Dinámico: devuelve un nuevo valor cada vez que se invoca durante la evaluación de consultas. Devuelve la hora del equipo local. Devuelve la hora UTC. Marca de tiempo local rápida sin contexto de zona horaria
DateTimeZone.LocalNow Valor datetimezone que representa la hora local actual con desplazamiento de zona horaria Dinámico: devuelve un nuevo valor cada vez que se invoca durante la evaluación de consultas. Devuelve la hora local con desplazamiento. Devuelve la hora UTC con +00:00 desplazamiento. Hora local con reconocimiento de zona horaria
DateTime.FixedLocalNow Valor datetime que representa la hora local cuando se invoca por primera vez durante la evaluación de consultas. Corregido: devuelve el mismo valor durante una única evaluación de consulta. Captura la hora local cuando se llama por primera vez Captura el tiempo UTC la primera vez que se llama. Instantánea de la hora local sin zona horaria
DateTimeZone.FixedLocalNow Valor datetimezone que representa la hora local con desplazamiento cuando se invoca por primera vez durante la evaluación de consultas. Corregido: devuelve el mismo valor durante una única evaluación de consulta. Captura la hora local con desplazamiento horario cuando se llama por primera vez Captura la hora UTC con un desplazamiento de +00:00 cuando se llama por primera vez Instantánea de la hora local con zona horaria
DateTimeZone.UtcNow Valor datetimezone que representa la hora UTC actual Dinámico: devuelve un nuevo valor cada vez que se invoca durante la evaluación de consultas. Devuelve la hora UTC actual. Devuelve la hora UTC actual. Marca de tiempo UTC coherente para escenarios dinámicos
DateTimeZone.FixedUtcNow Valor datetimezone que representa la hora UTC cuando se invoca por primera vez durante la evaluación de consultas. Corregido: devuelve el mismo valor durante una única evaluación de consulta. Captura el tiempo UTC la primera vez que se llama. Captura el tiempo UTC la primera vez que se llama. Marca de tiempo UTC fija para el registro o la auditoría

En Power Query M, elegir entre las funciones de fecha y hora locales y las funciones de fecha y hora basadas en UTC es una decisión de diseño crítica que afecta a la coherencia, la precisión y la portabilidad de las consultas. Las funciones como DateTime.LocalNow y DateTime.FixedLocalNow son útiles cuando la lógica depende de la hora del sistema local, como filtrar los registros que se produjeron "hoy" o generar marcas de tiempo para informes orientados al usuario. Estas funciones reflejan la zona horaria del entorno en el que se ejecuta la consulta, lo que las convierte en adecuadas para escenarios de Power Query Desktop en los que el contexto local está bien definido.

Sin embargo, en entornos distribuidos o basados en la nube, como Power Query Online, estas mismas funciones devuelven la hora UTC, no la hora local real del usuario. Esta discrepancia puede provocar incoherencias sutiles si la lógica asume un contexto de hora local. Por el contrario, DateTimeZone.UtcNow y DateTimeZone.FixedUtcNow proporcionan un punto de referencia neutral de zona horaria coherente entre entornos y que no se ve afectado por el horario de verano o la configuración regional. Estas funciones basadas en UTC son la opción preferida para escenarios que implican la integración de datos, el registro, la auditoría o cualquier lógica que se comporte de forma idéntica independientemente de dónde o cuando se ejecute la consulta.

Diferencias entre las funciones LocalNow y FixedLocalNow

Power Query M proporciona cuatro funciones para recuperar la hora local actual:

  • DateTime.LocalNow devuelve el valor local datetime actual cada vez que se evalúa la expresión.
  • DateTime.FixedLocalNow devuelve el valor local datetime una vez por evaluación de consultas, que actúa como una instantánea.
  • DateTimeZone.LocalNow devuelve el valor local datetimezone actual cada vez que se evalúa la expresión.
  • DateTimeZone.FixedLocalNow devuelve el valor local datetimezone una vez por evaluación de consultas, que actúa como una instantánea.

Para demostrar la diferencia, en el ejemplo siguiente se genera una tabla con varias filas. Cada fila captura un valor nuevo DateTime.LocalNow mediante un retraso para garantizar marcas de tiempo distintas, mientras que cada valor capturado DateTime.FixedLocalNow permanece constante en todas las filas.

Nota:

Todas las fechas y horas de la salida de los ejemplos de este artículo dependen de cuándo se ejecutan las funciones. Las fechas y horas que se muestran en la salida son solo con fines de demostración.

let
    // Create a table with LocalNow and FixedLocalNow columns 
    TableWithTimes = Table.FromList(
        {1..5},
        each {
            _,
            Function.InvokeAfter(() => DateTime.LocalNow(), #duration(0, 0, 0, 0.2)),
            Function.InvokeAfter(() => DateTime.FixedLocalNow(), #duration(0, 0, 0, 0.2))
        },
        {"Index", "LocalNow", "FixedLocalNow"}
    ),

    // Format both datetime columns
    FormatLocalNow = Table.TransformColumns(TableWithTimes, 
        {{"LocalNow", each DateTime.ToText(_, "yyyy-MM-ddThh:mm:ss.fff")}}),
    FormatFixedNow = Table.TransformColumns(FormatLocalNow, 
        {{"FixedLocalNow", each DateTime.ToText(_, "yyyy-MM-ddThh:mm:ss.fff")}}),

    // Change the table types
    FinalTable =  Table.TransformColumnTypes(FormatFixedNow, {{"Index", Int64.Type}, 
        {"LocalNow", type text}, {"FixedLocalNow", type text}})

in
    FinalTable

La salida de este ejemplo es:

Captura de pantalla de la tabla creada por DateTime.LocalNow con fechas y horas dinámicas y DateTime.FixedLocalNow con fechas y horas fijas.

Si observa la salida, es posible que pueda notar que aunque la DateTime.LocalNow función aparezca primero en el código, el valor devuelto para DateTime.FixedLocalNow muestra una hora que ocurre antes de la hora de DateTime.LocalTime. DateTime.LocalNow Aunque se muestra primero en la construcción de la tabla, no se garantiza que el orden de evaluación en Power Query M siga el orden de los campos de una tabla. En su lugar, Power Query utiliza un modelo de evaluación perezosa. El uso de este modelo significa que los campos solo se evalúan cuando es necesario y el motor determina el orden de evaluación, no el orden en el código. En este caso, la DateTime.FixedLocalNow función se evalúa primero, por lo que la primera vez que se devuelve para esta función se produce antes de la primera vez que se devuelve para DateTime.LocalNow.

En el ejemplo siguiente se muestra cómo generar resultados similares mediante DateTimeZone.LocalNow y DateTimeZone.FixedLocalNow.

let
    // Create a table with LocalNow and FixedLocalNow columns 
    TableWithTimes = Table.FromList(
        {1..5},
        each {
            _,
            Function.InvokeAfter(() => DateTimeZone.LocalNow(), #duration(0, 0, 0, 0.2)),
            Function.InvokeAfter(() => DateTimeZone.FixedLocalNow(), #duration(0, 0, 0, 0.2))
        },
        {"Index", "LocalNow", "FixedLocalNow"}
    ),

    // Format both datetimezone columns
    FormatLocalNow = Table.TransformColumns(TableWithTimes, 
        {{"LocalNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),
    FormatFixedNow = Table.TransformColumns(FormatLocalNow, 
        {{"FixedLocalNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),

    //  Change the table types
    FinalTable =  Table.TransformColumnTypes(FormatFixedNow, 
        {{"Index", Int64.Type}, {"LocalNow", type text}, {"FixedLocalNow", type text}})
in
    FinalTable

La salida de este ejemplo en Power Query Desktop es:

Captura de pantalla de la tabla creada por DateTimeZone.LocalNow con fechas y horas dinámicas y DateTimeZone.FixedLocalNow con fechas y horas fijas.

Nota:

Si ejecuta este ejemplo en Power Query Online, la hora devuelta siempre es la hora UTC y la parte de zona horaria de los valores devueltos siempre es +00:00.

Diferencias entre las funciones UtcNow y FixedUtcNow

Power Query M proporciona dos funciones para recuperar la hora UTC actual:

  • DateTimeZone.UtcNow devuelve la hora UTC datetimezone actual cada vez que se evalúa la expresión.
  • DateTimeZone.FixedUtcNow devuelve el valor local datetimezone una vez por evaluación de consultas, que actúa como una instantánea.

Las diferencias entre estas dos funciones son similares a las funciones LocalNow y FixedLocalNow. Sin embargo, si las funciones se ejecutan en Power Query Desktop o Power Query Online, los valores devueltos siempre se devuelven como hora UTC. En el ejemplo siguiente se muestran las diferencias entre estas dos funciones.

let
    // Create a table with UtcNow and FixedUtcNow columns 
    TableWithTimes = Table.FromList(
        {1..5},
        each {
            _,
            Function.InvokeAfter(() => DateTimeZone.UtcNow(), #duration(0, 0, 0, 0.2)),
            Function.InvokeAfter(() => DateTimeZone.FixedUtcNow(), #duration(0, 0, 0, 0.2))
        },
        {"Index", "UtcNow", "FixedUtcNow"}
    ),

    // Format both datetimezone columns
    FormatLocalNow = Table.TransformColumns(TableWithTimes, 
        {{"UtcNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),
    FormatFixedNow = Table.TransformColumns(FormatLocalNow, 
        {{"FixedUtcNow", each DateTimeZone.ToText(_, "yyyy-MM-ddThh:mm:ss.fff:zzz")}}),

    //  Change the table types
    FinalTable =  Table.TransformColumnTypes(FormatFixedNow, 
        {{"Index", Int64.Type}, {"UtcNow", type text}, {"FixedUtcNow", type text}})
in
    FinalTable

La salida de este ejemplo en Power Query Desktop y Power Query Online es:

Captura de pantalla de la tabla creada por DateTimeZone.UtcNow con fechas y horas dinámicas y DateTimeZone.FixedUtcNow con fechas y horas fijas.

Efectos en otras funciones

Otras funciones de Power Query M que dependen de la fecha y hora actuales también pueden verse afectadas por cómo se devuelve la hora local en Power Query Desktop o Power Query Online. Por ejemplo, si usa la función DateTimeZone.ToLocal para convertir la hora UTC a hora local, todavía devuelve la hora UTC en Power Query Online.

Otro ejemplo es cualquier función que pueda usar la hora actual del sistema como parámetro. Estas funciones incluyen Date.Month, Date.DayOfYear, DateTime.IsInCurrentYear, DateTimeZone.ZoneHourso cualquier otra función que pueda evaluar la fecha y hora actuales.

En todas estas funciones, si la lógica depende de si un valor se encuentra dentro del día actual, la hora, el mes o el año, los resultados pueden diferir entre entornos. Estas diferencias entre entornos son especialmente perceptibles si la consulta se ejecuta cerca de un límite (por ejemplo, justo antes o después de medianoche, el inicio de un nuevo mes o un año nuevo). Si la coherencia es fundamental en distintos entornos, use las DateTimeZone.UtcNow funciones o DateTimeZone.FixedUtcNow para recuperar la fecha y hora.

Procedimientos recomendados y recomendaciones

Elegir la función de hora adecuada en Power Query depende de su caso de uso específico, el entorno en el que se ejecuta la consulta (escritorio frente a en línea) y si necesita una marca de tiempo dinámica o fija. Estos son algunos procedimientos recomendados para ayudar a guiar su decisión:

  • Ser explícito sobre las zonas horarias: use las funciones DateTimeZone en lugar de las funciones DateTime cuando importa el contexto de zona horaria. Use DateTimeZone.UtcNow o DateTimeZone.FixedUtcNow para mantener la coherencia entre entornos, especialmente en soluciones basadas en la nube, como el servicio Power BI.
  • Usar funciones fijas para resultados repetibles: use las variantes fijas (como DateTimeZone.FixedUtcNow) cuando desee que la marca de tiempo permanezca constante en las evaluaciones de consulta. Este método es especialmente útil para registrar, auditar o capturar el tiempo de ingesta de datos.
  • Evite las funciones locales en Power Query Online: funciones como DateTime.LocalNow y DateTimeZone.LocalNow devuelven la hora UTC en soluciones basadas en la nube como el servicio Power BI, lo que puede provocar confusión o suposiciones incorrectas. Si necesita una hora local real en el servicio, considere la posibilidad de ajustar las UTC manualmente mediante desplazamientos conocidos (aunque este ajuste puede ser frágil, por ejemplo, debido al horario de verano o a la configuración regional).
  • Prueba en entornos de escritorio y en línea: pruebe siempre las consultas tanto en Power Query Desktop como en Power Query Online si la lógica depende de la hora actual. Esta prueba ayuda a detectar discrepancias al principio, especialmente para escenarios de actualización programados.
  • Documentar la lógica de tiempo: comenta o documenta claramente por qué se usa una función de hora específica, especialmente si usa una solución alternativa para el control de zonas horarias. Esta información ayuda a los colaboradores futuros a comprender la intención detrás de la lógica.
  • Usar UTC para flujos de trabajo programados: para actualizaciones programadas o canalizaciones automatizadas, UTC es la opción más segura y predecible. Evita ambigüedades causadas por el horario de verano o los turnos de zona horaria regionales.
  • Valores de tiempo de caché cuando sea necesario: si necesita usar la misma marca de tiempo en varios pasos de una consulta, asígnela a una variable en la parte superior de la consulta mediante una función fija. Esta variable garantiza la coherencia en toda la lógica de transformación.