VB .NET - Datas, horas: conceitos e operações (TimeSpan, DateTime)
No artigo de hoje vou mostrar como podemos tratar datas, horas e realizar algumas operações usando os objeto TimeSpan e DateTime. |
O objeto TimeSpan
Um objeto TimeSpan representa um intervalo de tempo, ou duração de tempo, medida como um número positivo ou negativo de dias, horas, minutos, segundos e frações de segundo.
Leia também o artigo : VB .NET - Tratamento de datas e horas
A unidade de tempo usada para medir a maior duração é um dia. Intervalos de tempos são medidos em dias pois o número de dias pois o número de dias em unidades de tempo , como meses e anos, sofre variação.
Um TimeSpan pode ser representado como [-.] d. hh: mm: ss. ff, onde :
- o sinal
indica um intervalo de tempo negativo;
- d indica dias;
- hh representa as horas medida em 24 horas;
- mm representa os minutos;
- ss representa os segundos;
- ff representa as frações de segundo.
Assim , a representação de texto de um objeto TimeSpan com 1.0E + ticks 13 é 11.13:46:40 que significa 11 dias , 13 horas , 46 minutos e 40 segundos.
Obtendo a data e hora do sistema
O namespace System.DataTime permite o acesso a métodos e propriedades que tratam datas e horas. A seguir temos os principais métodos e o tipo do retorno.
Método | Tipo Retorno |
Date Day DayOfWeek DayOfYear Hour Millisecond Minute Month Now Second Ticks TimeOfDay Today Year |
DateTime Int32 Int32 Int32 Int32 nt32 Int32 Int32 DateTime Int32 Int64 TimeSpan DateTime Int32 |
O tipo DateTime representa datas e horas com valores entre a meia-noite de 1 de janeiro de 0001 e 11:59:59 de 31 de dezembro de 9999.
Os valores de hora são medidos em unidades de 100 nano segundos chamadas Ticks sendo que uma data especifica é o número de pulsos contados a partir da meia-noite de 01/01/0001 no calendário Gregoriano.
A propriedade Now retorna a data na qual você pode armazenar em uma variável Date ou processar diretamente. Existem muitas propriedades e métodos disponíveis para extrair informações a partir de Datas. O exemplo abaixo extrai e exibe a data , a hora e os ticks transcorridos;
Private
Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click Dim datahoraAtual As DateTime = Now lstDataHora.Items.Add("Agora") lstDataHora.Items.Add("") lstDataHora.Items.Add(datahoraAtual) lstDataHora.Items.Add("") lstDataHora.Items.Add("Data : " & datahoraAtual.ToShortDateString) lstDataHora.Items.Add("Hora : " & datahoraAtual.ToShortTimeString) lstDataHora.Items.Add("Ticks : " & datahoraAtual.Ticks.ToString) End Sub |
Usei as propriedades ToShortDateString
e ToShortTimeString para extrair a data e a hora
para um formato mais legível.
Nota: O
VB6 armazena a data e a hora em um formato diferente do VB.NET os
programadores VB acessavam os valores numéricos de datas como um
Double. As datas no VB.NET são
armazenadas como inteiro longo em um formato incompatível com o
do VB6. Portanto na migração é melhor reescrever o seu código
usando o novo recurso para data. Para converter uma informação
de data no formato antigo para o novo formato use as funções : ToOADate() e FromOADate() que são específicas
para este propósito.
Migração VB->VB.NET : Quando
você for trabalhar com datas utilize o tipo Date e evite
Double. O VB6.0 permite que você use o tipo Double para armazenar datas , este tipo usa quatro bytes . No VB.NET uma variável do tipo Date usa o tipo de dado DateTime que é um inteiro de 8 bytes ; portanto não podemos converte Double para Date no VB.NET. O código abaixo é válido no VB 6.0 mas causa um erro de compilação no VB.NET.
Embora o VB.NET forneça as funções ToOAdate e FromOADate para converte double e date , durante a migração fica difícil determinar a sua intenção em usar Double para armazenar datas. Portanto sempre use o tipo Date para armazenar datas. |
Se você quiser determinar o fuso horário local ou o horário de verão local pode usar o objeto TimeZone que fornece propriedades e métodos para determinar o nome da da área , o número de horas do fuso horário a partir de Greenwich (GMT) e se o horário de verão local esta em uso.
Abaixo temos um exemplo que mostra a utilização do objeto TimeZone.
Private
Sub Button1_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles Button1.Click Dim fusoHorario As TimeZone = TimeZone.CurrentTimeZone lstTimeZone.Items.Add("DaylightName: " & fusoHorario.DaylightName) lstTimeZone.Items.Add("") lstTimeZone.Items.Add("StandardName: " & fusoHorario.StandardName) lstTimeZone.Items.Add("") lstTimeZone.Items.Add("IsDaylightSavingTime(Now): " & fusoHorario.IsDaylightSavingTime(Now)) lstTimeZone.Items.Add("") lstTimeZone.Items.Add("Fuso horário em relação a GMT [GetUtcOffset(Now)] : " & fusoHorario.GetUtcOffset(Now).ToString) lstTimeZone.Items.Add("") lstTimeZone.Items.Add("Hora do Sistema é Hora Local: DateTimeKind.Local = " & DateTimeKind.Local) 'lstTimeZone.Items.Add(Now.Kind = DateTimeKind.Local) lstTimeZone.Items.Add("Hora do Sistema é Universal Coordinated Time: DateTimeKind.Utc = " & DateTimeKind.Utc) lstTimeZone.Items.Add("") 'lstTimeZone.Items.Add(Now.Kind = DateTimeKind.Utc) lstTimeZone.Items.Add("Hora do Sistema não esta especificado: Now.Kind = " & DateTimeKind.Unspecified) 'lstTimeZone.Items.Add(Now.Kind = DateTimeKind.Unspecified) End Sub |
A variável fusohorario é definida como do tipo TimeZone e recebe a informação do fuso horário do sistema atual na sequência estamos extraindo as informações desejadas como: nome da zona local, o número de horas do fuso horário local em relação a GMT e se o horário de verão esta em uso.
A propriedade Kind é um de 2 bits que indica se a DateTime estrutura representa um horário local, um horário universal coordenado (UTC). Ela obtém um valor que indica se a hora representada por essa instância é baseada no horário local, hora universal coordenada (UTC), ou nenhum. Ela é usada também para tratar conversões entre local e hora UTC. Esta propriedade pertence a Date e não a TimeZone.
Nota:
O Horário local é relativo a um fuso horário
específico. Um fuso horário está associado a um
deslocamento de fuso horário, que é o deslocamento do
fuso horário medido em horas a partir do ponto de origem
UTC. Além disso, o horário local opcionalmente é
afetado pelo horário de verão, que adiciona ou subtrai
algumas horas ao dia. Enquanto que a Hora UTC é adequada para cálculos, comparações, e armazenamento datas e horas em arquivos o Horário local é apropriado para exibição em interfaces de usuário. |
Os cálculos usando uma estrutura DateTime, tais como somar ou subtrair, não modificam o valor da estrutura. Em vez disso, o cálculo retorna uma nova estrutura DateTime cujo valor é o resultado de cálculo.
Operações de conversão entre hora local e hora UTC devem levar o horário de verão em conta, mas não as operações aritméticas e de comparação.
Os cálculos e comparações de objetos DateTime são significativas se os objetos representam horas no mesmo fuso horário. Por esse motivo, se nenhuma zona de tempo for especificada para os objetos, estará pressuposto que o desenvolvedor tem algum mecanismo externo, como uma variável explícita ou diretiva, que pode ser usada para determinar o fuso horário no qual um objeto DateTime foi criado.
Cada membro DateTime usa implicitamente o calendário gregoriano para executar sua operação, com exceção de construtores que especificam um calendário.
Operações para membros do tipo DateTime leva em detalhes o número de dias em um mês e anos bissexto.
Vejamos a seguir alguns cálculos usando o namespace DateTime:
leia também o artigo : VB.NET Medindo diferença de tempos
Somando e subtraindo datas
Private
Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load Dim datahoraAtual As DateTime = Now lstDataHora.Items.Add(datahoraAtual) lstDataHora.Items.Add("") lstDataHora.Items.Add("Um ano atrás : " & datahoraAtual.AddYears(-1)) lstDataHora.Items.Add("No ano seguinte : " & datahoraAtual.AddYears(+1)) lstDataHora.Items.Add("No mês seguinte : " & datahoraAtual.AddMonths(+1)) lstDataHora.Items.Add("No mês anterior : " & datahoraAtual.AddMonths(-1)) lstDataHora.Items.Add("No dia anterior : " & datahoraAtual.AddDays(-1)) lstDataHora.Items.Add("No próximo dia : " & datahoraAtual.AddDays(+1)) End Sub |
Note que o objeto DateTime não possui um método para subtrair datas/horas mas podemos usar o método Add e usar argumentos com valores negativos para obter o mesmo resultado.
O objeto DateTime
possui um método Subtract mas este
método subtrai outro valor do tipo Date
ou do tipo TimeSpan.Abaixo temos o
método Subtract e os argumentos usados:
|
Existem 7 métodos que podemos usar para somar unidades de tempo a uma data:
AddYears()
AddMonths()
AddDays()
AddHours()
AddMinutes()
AddSeconds()
AddMilliseconds()
Determinando o número de dias entre duas datas
Para calcular o número de dias entre duas datas podemos usar o método Subtract da classe DateTime. Primeiro calculamos o TimeSpan entre duas datas e em seguida usando a propriedade Days da classe TimeSpan extraímos o número de dias.
O objeto TimeSpan representa a diferença de tempo entre duas datas , podemos subtrair uma data de outra data usando o método Subtract o qual retorna um TimeSpan. Para acessar as unidades de tempo a partir do TimeSpan , usamos as propriedades para cada tipo de unidade de tempo. Vejamos a seguir um exemplo que calcula o número de dias de vida de uma pessoa calculados a partir da data do seu nascimento até o dia de hoje.
Crie um novo projeto no VB 2005 Express Edition com um nome sugestivo e no formulário padrão inclua um controle DateTimePicker e alguma Labels.
a seguir inclua o seguinte código no formulário:
Private Function calculaNumeroDiasVividos() As IntegerDim dataNascimento As Date Dim horasVividas As TimeSpan Dim diasVividos As Integer
dataNascimento = dtpDataNascimento.Value
horasVividas = Now.Subtract(dataNascimento) diasVividos = horasVividas.Days
Throw New ArgumentException("Você ainda não nasceu...") End If
Return diasVividos
End
Function
Try lblDiasVividos.Text = calculaNumeroDiasVividos()
Catch exc As
Exception End Try Else MessageBox.Show("Informe uma data válida", "Data Inválida", MessageBoxButtons.OK, MessageBoxIcon.Error) End If End Sub
|
A rotina calculaNumeroDiasVividos calcula o número de dias entre as duas datas e é chamada toda vez que ocorre o evento ValueChanged do controle DateTimePicker. (Talvez não fosse uma boa idéia usar esta lógica, devido ao tratamento de erro que eu implementei...)
Os membros da classe TimeSpan que podemos usar para calcular a diferença entre datas são: Days, Hours, Minutes, Seconds, e Milliseconds. No exemplo usamos o método Days. Note que se o número de dias vividos for menor que 1 lançamos uma exceção.
Cada um dos membros retorna um valor inteiro arredondado indicando a diferença entre duas datas(hora).
Temos também as propriedades TotalDays, TotalHours, TotalMinutes, TotalSeconds, e TotalMilliseconds que retornam valores decimais que não são arredondados para o próximo intervalo.
Determinando o dia da semana
Para obter um número ou string representando o dia da semana para uma data você pode usar a propriedade DayOfWeek que retorna um número de 0 (Domingo) até 6 (Sábado) para o dia da semana , ou se preferir, usar o método ToString() para retornar o nome do dia semana. Você pode ainda usar as várias opções de formatação de string através do método String.Format() para retornar o nome do dia da semana no formato abreviado ou expandido.
O código abaixo mostra como usar estes recursos exibindo o dia da semana nos formatos números, abreviado e expandido:
Dim dataAtual As Date = Now Dim diaDaSemana As Integer = dataAtual.DayOfWeek Dim diaDaSemanaAbreviado As String = Format(dataAtual, "ddd") Dim diaDaSemanaExpandido As String = String.Format("{0:dddd}", dataAtual) Dim resultado As String = String.Format("Hoje é o dia da semana : {0}, ou {1}, ou {2}", diaDaSemana, diaDaSemanaAbreviado, diaDaSemanaExpandido) MsgBox(resultado) |
Determinando o dia do ano
Para determinar o dia do ano para uma data você pode usar a propriedade DayOfYear. O número obtido se situa no intervalo de 1 a 366.
O código abaixo obtém o dia do ano para a data atual:
Dim dataAtual As Date = Now Dim diaDoAno As Integer = dataAtual.DayOfYear Dim resultado As String = String.Format("Dia do ano para {0:D}: {1}", Now, diaDoAno) MsgBox(resultado) |
Determinar o número de dias em um Mês
Para obter o número de dias em um mês você pode usar a função DaysInMonth fornecida pelo objeto Date que retorna o número de dias em um mês para um determinado mês do ano. DaysInMonth é uma função compartilhada ou shared function.
O código a seguir mostra a sintaxe correta para obter o número de dias no mês atual:
Dim diasNoMes As Integer = Date.DaysInMonth(Now.Year, Now.Month) MsgBox(String.Format("Número de dias no mês atual: {0}", diasNoMes)) |
Calculando se um ano é bissexto
Para verificar se um ano é bissexto podemos usar o método IsLeapYear() do objeto Date. Este método retorna True se o ano passado como argumento for um ano bissexto e Fase caso contrário.
Dim anoBissexto As Boolean = Date.IsLeapYear(Now.Year) MsgBox(String.Format("{0} É um ano bissexto ? {1}", Now.Year, IIf(anoBissexto, "SIM", "NÃO"))) |
Perceba que o método IsLeapYear é um método estático (shared) por este motivo devemos chamá-lo diretamente do objeto Date e não a partir de uma instância deste objeto.
E por enquanto é só. Até o próximo artigo...
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências: