.NET

1 ago, 2024

Novidades do .NET 9: melhorias no tipo TimeSpan

Publicidade

O tipo TimeSpan é empregado comumente na plataforma .NET para definir intervalos de tempo, contando com diversas opções de métodos (iniciados por From) para produzir essas representações. Implementações como FromDaysFromHoursFromMinutesFromSecondsFromMilliseconds e FromMicroseconds recebem como parâmetro um valor do tipo double, gerando assim uma representação de tempo correspondente.

A utilização de valores double pode, no entanto, resultar em problemas de precisão ao trabalharmos com intervalos de tempo. Devemos lembrar que double é um tipo numérico de ponto flutuante, com a execução do código a seguir produzindo alguns resultados imprecisos:

string[] amostrasTempo = ["71.715", "71.716", "71.829", "71.830", "71.832"];
foreach (var amostra in amostrasTempo)
{
    Console.WriteLine();
    var amostraSegundos = JsonSerializer.Deserialize<double>(amostra);
    Console.WriteLine($"Tempo em segundos = {amostra}");
    Console.WriteLine($"Tempo em segundos (double) = {amostraSegundos}");
    var amostraTimeSpan = TimeSpan.FromSeconds(value: amostraSegundos);
    Console.WriteLine($"Tempo em segundos (TimeSpan) = {amostraTimeSpan} | TimeSpan.FromSeconds(value)");
}

Intervalos de tempo em segundos como 71.71671.829 e 71.832 exemplificam bem isso – conforme observamos em Tempo em segundos (TimeSpan):

Tempo em segundos = 71.715
Tempo em segundos (double) = 71,715
Tempo em segundos (TimeSpan) = 00:01:11.7150000 | TimeSpan.FromSeconds(value)

Tempo em segundos = 71.716
Tempo em segundos (double) = 71,716
Tempo em segundos (TimeSpan) = 00:01:11.7159999 | TimeSpan.FromSeconds(value)

Tempo em segundos = 71.829
Tempo em segundos (double) = 71,829
Tempo em segundos (TimeSpan) = 00:01:11.8289999 | TimeSpan.FromSeconds(value)

Tempo em segundos = 71.830
Tempo em segundos (double) = 71,83
Tempo em segundos (TimeSpan) = 00:01:11.8300000 | TimeSpan.FromSeconds(value)

Tempo em segundos = 71.832
Tempo em segundos (double) = 71,832
Tempo em segundos (TimeSpan) = 00:01:11.8319999 | TimeSpan.FromSeconds(value)

.NET

Buscando evitar inconsistências decorrentes do uso de double, o .NET 9 traz novas sobrecargas com parâmetros baseados em tipos inteiros para os métodos FromDaysFromHoursFromMinutesFromSecondsFromMilliseconds e FromMicroseconds.

Na próxima listagem temos a geração de instâncias de TimeSpan utilizando a nova sobrecarga de FromSeconds, que conta com parâmetros do tipo long para gerar uma nova representação de intervalo (linhas 25 e 26):

using System.Runtime.InteropServices;
using System.Text.Json;

Console.WriteLine("***** Testes com .NET 9 | Sobrecarga metodo FromSeconds - TimeSpan *****");
Console.WriteLine($"Versao do .NET em uso: {RuntimeInformation
    .FrameworkDescription} - Ambiente: {Environment.MachineName} - Kernel: {Environment
    .OSVersion.VersionString}");

string[] amostrasTempo = ["71.715", "71.716", "71.829", "71.830", "71.832"];
foreach (var amostra in amostrasTempo)
{
    Console.WriteLine();
    var valorAmostra = JsonSerializer.Deserialize<double>(amostra);
    Console.WriteLine($"Tempo em segundos = {amostra}");
    Console.WriteLine($"Tempo em segundos (double) = {valorAmostra}");
    TimeSpan amostraTimeSpan;
    amostraTimeSpan = TimeSpan.FromSeconds(value: valorAmostra);
    Console.WriteLine($"Tempo em segundos (TimeSpan) = {amostraTimeSpan} | TimeSpan.FromSeconds(value)");
    
    var partesAmostra = amostra.Split('.');
    var amostraSegundos = long.Parse(partesAmostra[0]);
    Console.WriteLine($"Segundos (long) = {amostraSegundos}");
    var amostraMilissegundos = long.Parse(partesAmostra[1]);
    Console.WriteLine($"Milissegundos (long) = {amostraMilissegundos}");
    amostraTimeSpan = TimeSpan.FromSeconds(
        seconds: amostraSegundos, milliseconds: amostraMilissegundos);
    Console.WriteLine(
        $"Tempo em segundos (TimeSpan) = {amostraTimeSpan} | TimeSpan.FromSeconds(seconds, milliseconds)");
}

Ao executar esta aplicação de testes:

Clique nesta imagem para visualizar com uma melhor resolução

Podemos notar que as inconsistências não mais ocorreram ao invocar a nova sobrecarga do método FromSeconds em TimeSpan:

Clique nesta imagem para visualizar com uma melhor resolução

Essa aplicação foi disponibilizada no GitHub:

https://github.com/renatogroffe/DotNet9-ConsoleApp-TimeSpan

Caso achem útil esta solução, peço por favor um ⭐️ no repositório apoiando. Fica também o convite para que vocês me sigam lá no GitHub!