msdn09_capa.JPG

Clique aqui para ler todos os artigos desta edição

 

Manipulando Datas e Horas com C# e VB .NET

por Marden Menezes

 

Manipulação de datas e horas em aplicações é um processo bastante comum e que se faz presente em variados tipos de softwares, desde simples cadastros até os complexos sistemas de gerenciamento de datas e períodos de tempo. Nesse artigo mostrarei como manipular datas em .NET, as maneiras de formatação, cálculo e globalização de suas informações de tempo.

 

A classe DateTime

A principal classe para manipulação de datas em .NET é a DateTime do namespace System, que conta o tempo através de ticks (cada tick representa 100 nano segundos) desde 01/01/0001 até 31/12/9999. A classe DateTime possui diversos métodos e propriedades estáticas que nos permitem manipular data e hora sem precisar criar instâncias de DateTime. Veja a Tabela 1.

 

Método/Propriedade

Descrição

DateTime.MinValue

Representa o valor mínimo, 01/01/0001 00:00:00.
É também o valor padrão de um objeto DateTime inicializado com construtor vazio.

DateTime.MaxValue

Representa o valor máximo, 31/12/9999 23:59:59

DateTime.Now

Retorna um objeto DateTime que representa a data e hora atual no computador

DateTime.Today

Retorna apenas a data atual no computador

DateTime.IsLeapYear(int ano)

Retorna um valor booleano indicando se o ano passado como parâmetro em formato de 4 dígitos é bissexto.

DateTime.Compare(DateTime d1, DateTime d2)

Método que retorna 0 se as duas datas forem iguais, 1 se d1 for maior e -1 se d2 for maior

DateTime.DayInMonth(int ano, int mes)

Retorna a quantidade de dias no mês do ano especificado.

Tabela 1. Alguns métodos e propriedades de System.DateTime

 

Além dos métodos e propriedade estáticas, há a possibilidade de criar objetos DateTime e manipulá-los utilizando seus métodos e propriedades. A Tabela 2 mostra alguns deles.

 

Método/Propriedade

Descrição

 

Date

Retorna a data representada nessa instância do objeto

TimeOfDay

Retorna o horário guardado nessa instância do objeto

AddHours(double valor)

Adiciona horas ao horário guardado no objeto. Há também métodos AddMinutes(), AddSeconds(), AddMiliSeconds() usando a mesma idéia.

AddDays(double valor)

Adiciona dias à data guardada no objeto. Há também métodos AddMonths(), AddYears() seguindo a mesma idéia.

Tabela 2. Alguns métodos e propriedades de um objeto criado do tipo DateTime

 

A Listagem 1 demonstra a criação de objetos DateTime e a utilização de alguns dos métodos e propriedades.

 

Listagem 1. Criação e utilização de objetos DateTime em C# e VB .NET

//código em C#

//cria um objeto DateTime representando o dia 23/12/2020, com horário 00:00:00

DateTime data = new DateTime(2020,12,23);

//cria outro objeto que representa a data e hora atual

DateTime dataAtual = DateTime.Now;

 

//se a data atual for anterior a 23/12/2020, imprima “Data anterior”

if (DateTime.Compare(dataAtual,data) == -1)

{

    Console.WriteLine(“Data anterior”);

}

 

//soma 50 anos a data atual:

dataAtual = dataAtual.AddYears(50);

 

//compara se a data atual é posterior a 23/12/2020:

if (DateTime.Compare(dataAtual,data) == 1)

{

    Console.WriteLine(“Data posterior”);

}

 

 

‘código em VB .NET

‘cria um objeto DateTime representando o dia 23/12/2020, com horário 00:00:00

Dim data As New DateTime(2020,12,23)

‘cria outro objeto que representa a data e hora atual

Dim dataAtual As DateTime = DateTime.Now

 

‘se a data atual for anterior a 23/12/2020, imprima “Data anterior”

If (DateTime.Compare(dataAtual,data) = -1) Then

    Console.WriteLine(“Data anterior”)

End If

 

‘soma 50 anos a data atual:

dataAtual = dataAtual.AddYears(50)

 

‘compara se a data atual é posterior a 23/12/2020:

If (DateTime.Compare(dataAtual,data) = 1) Then

    Console.WriteLine(“Data posterior”)

End If

 

Note que o método AddYears() (assim como qualquer outro método de adição em datas ou horas) não adiciona anos ao objeto que o está chamando diretamente. Ele adiciona o valor passado como argumento a uma cópia do objeto que o chama, retornando essa cópia após realizar a soma dos anos. Isso significa que é necessário atribuir o valor de retorno do  método a algum objeto. Veja um exemplo na Listagem 2.

 

Listagem 2. Utilização de AddYears() em C# e VB .NET

//código em C#

//não realiza nenhuma mudança no objeto dataAtual:

dataAtual.AddMonth(4);

//cria uma cópia do objeto dataAtual, modifica adicionando meses e retorna a cópia modificada
dataAtual = dataAtual.AddMonth(4);

 

‘código em VB .NET

‘não realiza nenhuma mudança no objeto dataAtual:

dataAtual.AddMonth(4)

‘cria uma cópia do objeto dataAtual, modifica adicionando meses e retorna a cópia modificada

dataAtual = dataAtual.AddMonth(4)

 

Formatando datas

Algo tão importante quanto saber trabalhar com datas é saber formatá-las para que sejam mostradas ao usuário final. Os projetistas do Visual Basic .NET trouxeram soluções quer permitem transformar a formatação de datas em algo extremamente trivial. O namespace Microsoft.VisualBasic nos traz o método FormatDateTime() que recebe uma expressão do tipo Date e um formato representado pela enumeração DateFormat. Você verá que Date é apenas uma forma de transformar o uso da classe DateTime mais fácil para os programadores que vieram do Visual Basic 6.0. Date é apenas um “alias” para DateTime, possuindo os mesmos métodos e propriedades, nos permitindo escolher qual das duas classes iremos usar sem nenhuma perda no nosso código. A  Tabela 3 mostra os tipos de formato que podemos usar.

 

Formato

Descrição

DateFormat.GeneralDate

Mostra a data e a hora. As configurações de data e hora são determinadas pelas configurações regionais do computador.

DateFormat.LongDate

Mostra apenas a data usando a configuração de data completa determinada pelas configurações regionais do computador.

DateFormat.ShortDate

Mostra apenas a data usando a configuração de data abreviada determinada pelas configurações regionais do computador.

DateFormat.LongTime

Mostra apenas a hora usando a configuração de hora completa determinada pelas configurações regionais do computador.

DateFormat.ShortTime

Mostra apenas a data usando a configuração de hora abreviada determinada pelas configurações regionais do computador.

Tabela 3. Formatos da enumeração DateFormat em VB .NET

 

A Listagem 3 mostra os diversos formatos a serem usados para exibir datas ao usuário utilizando o FormatDateTime() e a enumeração DateFormat de VB.NET. A execução do código é mostrada na Figura 1.

 

Listagem 3. Formatando datas em VB .NET com DateFormat

‘código em VB .NET

Sub Main()

‘cria um objeto DateTime representando a data 23/12/1982 as 13:00:40:00

‘é possível também usar Date ao invés de DateTime

Dim data As New DateTime(1982,12,23,13,0,40,0)

 

‘formata a data em vários formatos

Console.WriteLine(“Usando o formato GeneralDate: ” &   FormatDateTime(data,DateFormat.GeneralDate))

Console.WriteLine(“Data em formato LongDate: ”& FormatDateTime(data,DateFormat.LongDate))

Console.WriteLine(“Data em formato ShortDate: ”& FormatDateTime(data,DateFormat.ShortDate))

Console.WriteLine(“Hora em formato LongTime: ”& FormatDateTime(data,DateFormat.LongTime))

Console.WriteLine(“Hora em formato ShortTime: ”& FormatDateTime(data,DateFormat.ShortTime))

 

End Sub

 

image001.gif

Figura 1. Execução do código da Listagem 3

 

O método FormatDateTime() também permite a utilização de formatos personalizados para datas, possibilitando que escolhamos o formato que melhor se adeque as necessidades. Veja na Listagem 4 as possiblidades de personalizar datas com o método FormatDateTime().

 

Listagem 4. Personalizando a formatação das datas

‘código em VB .NET

Sub Main()

‘cria a data do tipo DateTime (lembrando que criar usando Date obtém o mesmo resultado em VB .NET )
Dim data As New DateTime(1982,12,23,13,0,40)
’DIAS

Console.WriteLine("<--Personalizando formatos dos dias-->")
Console.WriteLine("d: -> " & Format(data, "d"))
Console.WriteLine("dd: -> " & Format(data, "dd"))
Console.WriteLine("ddd: -> " & Format(data, "ddd"))
Console.WriteLine("dddd: -> " & Format(data, "dddd"))
’MESES

Console.WriteLine("<--Personalizando formatos dos meses-->")
Console.WriteLine("M: -> " & Format(data, "M"))
Console.WriteLine("MM: -> " & Format(data, "MM"))
Console.WriteLine("MMM: -> " & Format(data, "MMM"))
Console.WriteLine("MMMM: -> " & Format(data, "MMMM"))
’ANOS

Console.WriteLine("<--Personalizando formatos dos anos-->")
Console.WriteLine("y: -> " & Format(data, "y"))
Console.WriteLine("yy: -> " & Format(data, "yy"))
Console.WriteLine("yyyy -> " & Format(data, "yyyy"))
’HORAS

Console.WriteLine("<--Personalizando formatos de horas -->")
Console.WriteLine("hh: -> " & Format(data, "hh"))
Console.WriteLine("HH: -> " & Format(data, "HH"))
’MINUTOS

Console.WriteLine("<--Personalizando formatos dos minutos-->")
Console.WriteLine("mm: -> " & Format(data, "mm"))

’SEGUNDOS
Console.WriteLine("<--Personalizando formatos dos segundos-->")
Console.WriteLine("ss: -> " & Format(data, "ss"))
’FORMATOS ALEATÓRIOS, PERSONALIZADOS PELO DESENVOLVEDOR

Console.WriteLine("<--formatos criados pelo desenvolvedor -->")
Console.WriteLine("dd/MM/yyyy: -> " & Format(data, "dd/MM/yyyy"))
Console.WriteLine("MM/dd/yyyy: -> " & Format(data, "MM/dd/yyyy"))
Console.WriteLine("dd/MM: -> " & Format(data, "dd/MM"))
Console.WriteLine("dd ddd/MMM/yyyy: -> " & Format(data, "dd ddd/MMM/yyyy"))
Console.WriteLine("dd dddd/MMM/yyyy: -> " & Format(data, "dd dddd/MMM/yyyy"))
Console.WriteLine("dddd dd/MMM/yyyy: -> " & Format(data, "dddd dd/MMM/yyyy"))
End Sub

 

A execução do código da Listagem 4 é mostrada na Figura 2.

 

image003.jpg

Figura 2. Execução do código da listagem 4

Globalização

Em certas situações precisamos trabalhar com calendários diferentes do calendário gregoriano tradicional. O namespace System.Globalization permite trabalhar com diferentes tipos de calendários dependendo da aplicação. Veja na Tabela 4 as classes e os respectivos calendários o qual cada classe se relaciona. Todas as classes herdam de System.Globalization.Calendar.

 

Classe

Tipo do Calendário

GregorianCalendar

Calendário Gregoriano, o padrão no mundo ocidental. Possui várias versões de calendário, que pode ser definida pela enumeração GregorianCalendarTypes. O padrão é Localized, que utiliza a versão referente a localização setada no CultureInfo da aplicação. Apesar do calendário gregoriano possuir duas eras, B.C. (Before Christ) e A.C. (After Christ), só a era AC está implementada.

HebrewCalendar

Representa o calendário Hebreu. Esta implementação só reconhece do ano 5343 a 6000 (equivalente ao intervalo de 1582 a 2240 AC no calendário gregoriano).

HijriCalendar

O calendário Hijri contém apenas uma era, A.H. ("Anno Hegirae", que significa “o ano da migração”). A data 01 de janeiro de 2001  A.C. no calendário gregoriano representa o sexto dia do mês de Shawwal no ano de 1421 A.H. no calendário Hijri.

JapaneseCalendar

O calendário Japonês trabalha exatamente como o gregoriano, mas possui diversas eras que mudam a cada mudança de imperador. A era atual é a era Heisei, que começou no ano 1989 do calendário gregoriano.

JulianCalendar

O predecessor do calendário Gregoriano foi criado por Júlio César em 45 B.C.  É igual ao calendário Gregoriano em sua essência, diferindo apenas a data inicial e a forma de calcular anos bissextos. A data 01 de janeiro de 2001 A.C. no calendário gregoriano equivale a 19 de dezembro de 2000 no calendário Juliano.

KoreanCalendar

Também é semelhante ao calendário Gregoriano possuindo apenas ano inicial e era diferentes. Apenas a era atual está implementada e a data de 01 de janeiro de 2001 representa 01 de janeiro de 4334 da atual era do calendário Coreano.

TaiwanCalendar

Assim como o Coreano, é semelhante ao calendário gregoriano, moficando apenas o ano e a era. A data de 01 de janeiro de 2001 representa 01 de janeiro de 90 da atual era do calendário de Taiwan.

Tabela 4. Calendários disponíveis no namespace System.Globalization

 

O construtor da classe System.DateTime permite que criemos datas em diferentes calendários passando como argumento um objeto do tipo Calendar. Para convertermos uma data que está em um calendário para outro usamos os métodos específicos de cada calendário que recebem uma data em um determinado calendário e retornam o dia, o mês e o ano em outro calendário. A Listagem 5 exemplifica maneiras de trabalhar com conversão entre diferentes calendários.

 

Listagem 5. Conversão entre calendários em C# e VB .NET

//código em C#

//cria um objeto DateTime no calendário Gregoriano padrão representando a data 01/01/2001

DateTime gregoriano = new DateTime(2001,1,1);

 

//converte a data para o calendário Hebreu

//cria um objeto do tipo HebrewCalendar

HebrewCalendar calHebreu = new HebrewCalendar();

 

//transforma dia, mês e ano

int dia = calHebreu.GetDayOfMonth(gregoriano);

int mes = calHebreu.GetMonth(gregoriano);

int ano = calHebreu.GetYear(gregoriano);

Console.WriteLine(“Data no calendário hebreu: “ + dia + “/” + mes + “/” + ano);

 

//cria o objeto DateTime no calendário Hebreu

DateTime hebreu = new DateTime(ano,mes,dia,new HebrewCalendar());

 

//converte a data para o calendário Coreano

//cria um objeto do tipo KoreanCalendar

KoreanCalendar calCoreano = new KoreanCalendar ();

 

//transforma dia, mês e ano

dia = calCoreano.GetDayOfMonth(hebreu);

mes = calCoreano.GetMonth(hebreu);

ano = calCoreano.GetYear(hebreu);

Console.WriteLine(“Data no calendário coreano: “ + dia + “/” + mes + “/” + ano);

 

 

‘Código em VB .NET

‘cria um objeto DateTime no calendário Gregoriano padrão representando a data 01/01/2001

Dim gregoriano As DateTime = New DateTime(2001,1,1)

 

‘converte a data para o calendário Hebreu

‘cria um objeto do tipo HebrewCalendar

Dim calHebreu As HebrewCalendar = New HebrewCalendar()

 

‘transforma dia, mês e ano

Dim dia As Integer = calHebreu.GetDayOfMonth(gregoriano)

Dim mes As Integer = calHebreu.GetMonth(gregoriano)

Dim ano As Integer = calHebreu.GetYear(gregoriano)

Console.WriteLine(“Data no calendário hebreu: “ & dia & “/” & mes & “/” & ano)

 

‘cria o objeto DateTime no calendário Hebreu

Dim hebreu As New DateTime(ano,mes,dia,new HebrewCalendar())

 

‘converte a data para o calendário Coreano

‘cria um objeto do tipo KoreanCalendar

Dim calCoreano As New KoreanCalendar()

 

‘transforma dia, mês e ano

dia = calCoreano.GetDayOfMonth(hebreu)

mes = calCoreano.GetMonth(hebreu)

ano = calCoreano.GetYear(hebreu)

Console.WriteLine(“Data no calendário coreano: “ + dia + “/” + mes + “/” + ano)

 

Lembre-se que ao converter datas você estará trabalhando com diferentes calendários e que temos intervalos fixos implementados para cada calendário. Pode acontecer de uma data em um calendário específico possa estar fora do intervalo implementado para outro calendário. Isso causará uma exceção e você deverá estar apto a tratá-la ou a testar se a data está no intervalo válido antes de fazer a conversão.

Convertendo de objetos para datas

Uma preocupação constante é a forma de converter strings que representam datas (que foram, por exemplo, digitadas pelo usuário do sistema na interface gráfica) para objetos que representam datas. O .NET traz a classe System.Convert como uma solução para conversões de tipos. No caso de datas, a classe System.Convert nos traz o método ToDateTime() que pode transformar outros tipos de objetos em um DateTime.

Outra forma de conversão para datas é o CDate e o CType, métodos exclusivos de Visual Basic .NET. O resultado, na prática, é o mesmo da classe System.Convert, mas permite aos usuários de VB 6 usarem sintaxe parecida com o da linguagem a qual estão acostumados. Outro “açúcar sintático” criado para os desenvolvedores de Visual Basic .NET é a possibilidade do uso do tipo Date ao invés do DateTime. Na prática nada muda, o Date é apenas um “alias” para a classe DateTime, possuindo os mesmos métodos e propriedades da mesma.

Veja na Listagem 6 um código que recebe uma string do teclado, transforma em uma data, soma 21 dias a essa data e retorna a resposta ao usuário, que na verdade representa a data passada 3 semanas depois. Perceba que caso a conversão para uma data gere uma exception o método Convert.ToDateTime() gera a exception FormatException, diferentemente do CDate, que gera o InvalidCastException. É importante tratar os erros para evitar paradas inesperadas no fluxo de execução do programa.

 

Listagem 6. Conversão de string para data em C# e VB .NET

//código em C#

try {

 

//recebe uma string do teclado e armazena em um objeto do tipo string

string dataRecebida = Console.ReadLine();

 

//converte para um objeto DateTime

DateTime dataConvertida = Convert.ToDateTime(dataRecebida);

 

//soma 21 dias e retorna o resultado ao objeto

dataConvertida = dataConvertida.AddDays(21);

 

//imprime na tela o resultado

Console.WriteLine(“A data “ + dataConvertida + “ representa 3 semanas depois da data digitada”);

}

//caso a conversão não tenha sido bem sucedida

catch (FormatException ex) {

    Console.WriteLine(“O valor digitado não pode ser convertido para uma data”);

}

 

 

‘código em VB .NET usando System.Convert e System.DateTime

Try

 

‘recebe uma string do teclado e armazena em um objeto do tipo string

Dim dataRecebida As String = Console.ReadLine()

 

‘converte para um objeto DateTime

Dim dataConvertida As DateTime = Convert.ToDateTime(dataRecebida)

 

‘soma 21 dias e retorna o resultado ao objeto

dataConvertida = dataConvertida.AddDays(21)

 

‘imprime na tela o resultado

Console.WriteLine(“A data “ & dataConvertida & “ representa 3 semanas depois da data digitada”)

 

‘caso a conversão não tenha sido bem sucedida

Catch ex As FormatException

    Console.WriteLine(“O valor digitado não pode ser convertido para uma data”)

 

End Try

 

‘código em VB .NET usando CDate e Date

Try

 

‘recebe uma string do teclado e armazena em um objeto do tipo string

Dim dataRecebida As String = Console.ReadLine()

 

‘converte para um objeto Date

Dim dataConvertida As Date = CDate(dataRecebida)

 

‘soma 21 dias e retorna o resultado ao objeto

dataConvertida = dataConvertida.AddDays(21)

 

‘imprime na tela o resultado

Console.WriteLine(“A data “ & dataConvertida & “ representa 3 semanas depois da data digitada”)

 

‘A exception levantada é diferente do Convert.ToDateTime()

Catch ex As InvalidCastException

    Console.WriteLine(“O valor digitado não pode ser convertido para uma data”)

 

End Try

Conclusão

Vimos nesse artigo como é fácil criar, modificar e formatar datas na plataforma .NET, inclusive trabalhando com diversos calendários, desde o calendário Gregoriano usado no mundo ocidental até o extinto calendário Juliano, criado na época de Júlio César. Mostramos também técnicas de formatação de datas em Visual Basic .NET, que nos traz o método FormatDateTime(), aumentando a produtividade na hora de trabalhar com datas e mostrá-las ao usuário final do sistema.

 

Download disponível em http://www.neoficio.com.br/msdn

 

Referências:

Os seguintes artigos foram utilizados como referências e podem ajudá-lo a descobrir ainda mais sobre manipulação de datas em .NET:

Renato Haddad (http://www.msdnbrasil.com.br/tecnologias/visualbasic_hora.aspx)

José Carlos Macoratti (http://www.macoratti.net/vbn_data.htm)

Dan Rogers, da MSDN (http://msdn.microsoft.com/netframework/default.aspx?pull=/library/en-us/dndotnet/html/datetimecode.asp)