Como enviar e-mail no horário local de um usuário em .NET/Sql Server?
-
09-06-2019 - |
Pergunta
Estou escrevendo um programa que precisa enviar um e-mail de hora em hora, mas em um horário local para o usuário.
Digamos que tenho 2 usuários em fusos horários diferentes.John está em Nova York e Fred está em Los Angeles.O servidor está em Chicago.Se eu quiser enviar um e-mail às 18h local para cada usuário, terei que enviar o e-mail para John às 19h, horário do servidor, e para Fred, às 16h, horário do servidor.
Qual é uma boa abordagem para isso no .NET/Sql Server?Encontrei um arquivo xml com todas as informações de fuso horário, por isso estou pensando em escrever um script para importá-lo para o banco de dados e depois consultá-lo.
Editar: Usei “t4znet.dll” e fiz todas as comparações no lado .NET.
Solução
Você tem duas opções:
- Armazene o tempo ajustado para a ação de email no banco de dados para cada usuário.Depois é só comparar a hora do servidor com a hora armazenada.Para evitar confusão e problemas de portabilidade, eu armazenaria todos os horários em UTC.Portanto, envie e-mail quando SERVER_UTC_TIME() == armazenadoUtcTime.
- Armazene a hora local de cada ação de email no banco de dados e converta instantaneamente.Enviar e-mail quando SERVER_UTC_TIME() == TO_UTC_TIME(storedLocalTime, userTimeZone).
Você deve decidir o que faz mais sentido para sua aplicação.Por exemplo, se o horário de envio for sempre o mesmo para todos os usuários, faz mais sentido escolher a opção (2).Se os horários dos eventos puderem mudar entre usuários e até mesmo por usuário, o desenvolvimento e a depuração poderão ser mais fáceis se você escolher a opção (1).De qualquer forma, você precisará saber o fuso horário do usuário.
*Essas chamadas de função são obviamente pseudo, já que não conheço suas invocações em T-SQL, mas deveriam existir.
Outras dicas
Sou um desenvolvedor PHP, então compartilharei o que sei sobre PHP.Tenho certeza de que o .NET incluirá algo semelhante.
No PHP você pode obter diferenças de fuso horário para o horário do servidor - como você sugeriu, enviaria os e-mails em horários diferentes no servidor.
Cada vez que você adiciona um usuário, salve seu deslocamento de horário em relação ao horário do servidor (ou seu fuso horário, caso o fuso horário do servidor mude).
Então, quando você especificar uma atualização, tenha uma tarefa automatizada (Cron para pessoas do LAMP) que é executada a cada hora, verificando se um e-mail precisa ser enviado.Faça isso até que não haja mais e-mails para enviar.
Você pode complementar sua solução com este excelente artigo "Relógio mundial e a classe TimeZoneInformation", fiz um webservice que enviava um arquivo com informações que incluíam o local e o horário do receptor, o que fiz foi modificar essa classe para poder resolver aquele problema e funcionou perfeitamente, exatamente como eu precisava.
Acho que você poderia pegar essa aula e obter na tabela "Usuários" o fuso horário deles e "calcular" o horário apropriado, meu código ficou assim;
//Get correct destination time
DateTime thedate = DateTime.Now;
string destinationtimezone = null;
//Load the time zone where the file is going
TimeZoneInformation tzi = TimeZoneInformation.FromName(this.m_destinationtimezone);
//Calculate
destinationtimezone = tzi.FromUniversalTime(thedate.ToUniversalTime()).ToString();
Esta classe tem um problema no Windows Vista que trava a função "FromIndex(int index)", mas você pode modificar o código, em vez de usar a função:
public static TimeZoneInformation FromIndex(int index)
{
TimeZoneInformation[] zones = EnumZones();
for (int i = 0; i < zones.Length; ++i)
{
if (zones[i].Index == index)
return zones[i];
}
throw new ArgumentOutOfRangeException("index", index, "Unknown time zone index");
}
Você pode alterá-lo para;
public static TimeZoneInformation FromName(string name)
{
TimeZoneInformation[] zones = EnumZones();
foreach (TimeZoneInformation tzi in zones)
{
if (tzi.DisplayName.Equals(name))
return tzi;
}
throw new ArgumentOutOfRangeException("name", name, "Unknown time zone name");
}