Asp.Net, SQL e fusos horários

Foi perguntado, mas eu estou lutando para entender o conceito de como lidar com fusos horários em um aplicativo da web. Eu tenho um sistema que rastreia o progresso dos projetos. Eu tenho um ProjectStartDate DATE no meu banco de dados do SQL Server. (Há mais alguns campos e tabelas, mas vamos nos concentrar em um).

O servidor está localizado em algum lugar nos Estados Unidos. Eu moro na Australia.

ChamandoSELECT GETDATE() retorna "2013-08-11 14: 40: 50.630" Meu relógio do sistema mostra "2013-08-12 07:40"

No meu banco de dados, eu tenho colunas 'CreateDateTime' em todas as tabelas. Quando eu armazeno isso, dentro do meu código c #, eu usoCreateDate = DateTime.UtcNow

Eu uso isso, como ouvi dizer que era melhor usar o UTC.

Mas, quando um usuário recebe um controle de calendário e seleciona uma Data de Início para um projeto, eu armazeno o que quer que o usuário tenha selecionado. Nenhuma conversão ... E como eu disse, o StartDate é um tipo DATE no banco de dados.

O problema é, se um projeto começou hoje - meu front end diz que o projeto atual é No Started, porque o servidor ainda está em Ontem.

Eu acho que as datas devem ser armazenadas enquanto eu as armazeno. Mas talvez eu precise de alguma forma obter o fuso horário dos usuários e aplicar isso no nível da interface do usuário?

Problemas que vejo são:

Eu não sei o fuso horário dos usuários. Adicione algo para permitir que eles o selecionem?O status do projeto talvez determinado em um procedimento armazenado, então quando posso aplicar a conversão? No proc, ele pode fazer uma verificação e retornar um VARCHAR indicando "Não iniciado" se o StartDate <= DateTime.Now?

Eu uso EntityFramework e Linq para obter dados na maioria das vezes. Eu preciso de uma estratégia para inserir e recuperar dados, tanto de um sentido SQL, quanto de um sentido .Net.

Eu adicionei código para que o usuário selecione seu fuso horário com base nisso:

public List<TimeZoneDto> GetTimeZones()
{
    var zones = TimeZoneInfo.GetSystemTimeZones();
    var result = zones.Select(tz => new TimeZoneDto
        {
            Id = tz.Id, 
            Description = tz.DisplayName
        }).ToList();

    return result;
}

Isso é então persistido em seu perfil.

Todas as datas estão sendo armazenadas como UTC, conforme indicado nas respostas abaixo.

Ainda estou confuso sobre como lidar com as datas em que eles vão do banco de dados para o cliente. Aqui está um exemplo de como estou armazenando um registro:

public int SaveNonAvailibility(PersonNonAvailibilityDto n)
{
    person_non_availibility o;

    if (n.Id == 0)
    {
        o = new person_non_availibility
            {
                PersonId = n.PersonId,
                Reason = n.Reason,
                StartDate = n.StartDate,
                EndDate = n.EndDate,
                NonAvailibilityTypeId = n.NonAvailibilityTypeId,
                CreateUser = _userId,
                CreateDate = DateTime.UtcNow

            };
        _context.person_non_availibility.Add(o);
    }
    else
    {
        o = (from c in _context.person_non_availibility where c.Id == n.Id select c).FirstOrDefault();
        o.StartDate = n.StartDate;
        o.EndDate = n.EndDate;
        o.Reason = n.Reason;
        o.NonAvailibilityTypeId = n.NonAvailibilityTypeId;
        o.LastUpdateDate = DateTime.UtcNow;
        o.LastUpdateUser = _userId;
        o.Deleted = n.Deleted ? DateTime.UtcNow : (DateTime?)null;
    }
    _context.SaveChanges();
    return o.Id;
}

Este método basicamente salva quando uma pessoa não está disponível para o trabalho. Observe a maneira como eu armazeno o LastUpdateDate. Além disso, as datas 'Start' e 'End'. Essas datas são mais datas "comerciais".

Na seleção e, em seguida, na verificação da data, é onde tenho problemas. Neste exemplo, estou obtendo uma taxa de carga de pessoas, com base em NOW.

public decimal CurrentRate
{
    get
    {
        if (ResourceCosts != null)
        {
            var i = ResourceCosts.FirstOrDefault(t => DateTime.UtcNow <= (t.EndDate.HasValue ? t.EndDate.Value : DateTime.UtcNow) && DateTime.UtcNow >= t.StartDate);
            if (i != null) return i.Cost;
            return 0;
        }
        return 0;
    }
}

Então, o que eu estou querendo fazer aqui, é, com base na data atual, eu quero ver sua taxa (como sua taxa de carga talvez seja US $ 100 a partir de 1 de janeiro, a 15 de janeiro e, em seguida, US $ 110 a partir de 16 31 de janeiro Então, eu olho para a taxa aplicável hoje (se houver) .Esta não funciona em fusos horários, e é talvez aqui onde eu preciso fazer alguma manipulação de data com base no 'DateTime.UTCNow'?

Note, agora eu sei o fuso horário dos usuários com base no código acima, onde estou armazenando seu fuso horário. Eu posso usar isso de alguma forma aqui? Talvez, quando o usuário fizer login, pegue as informações de data de seu perfil (informações do Zimezone) e tenha uma função global compartilhada, que retorne a data / hora do usuário, com base na adição ou remoção de horas da Data UTC ... e usando essa onde eu estou fazendo DateTime.UTCNow?

Espero que alguém possa me guiar.

questionAnswers(2)

yourAnswerToTheQuestion