Exibir data / hora no formato de localidade do usuário e deslocamento de hora


167

Desejo que o servidor sempre atenda as datas no UTC no HTML e faça com que o JavaScript no site do cliente o converta no fuso horário local do usuário.

Bônus se eu puder imprimir no formato de data da localidade do usuário.

Respostas:


165

Parece que a maneira mais infalível de começar com uma data UTC é criar um novo Dateobjeto e usar os setUTC…métodos para configurá-lo para a data / hora desejada.

Em seguida, os vários toLocale…Stringmétodos fornecerão saída localizada.

Exemplo:

// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);

console.log(d);                        // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString());       // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString());   // -> 02/28/2004
console.log(d.toLocaleTimeString());   // -> 23:45:26

Algumas referências:


1
No Firefox, toLocateDateString()retorna algo parecido com 'Domingo, 12 de janeiro de 2014' ..
BlueRaja - Danny Pflughoeft

1
Hmm, sim, é um problema muito sério. O uso desses métodos não funcionará se você desejar que a data tenha a mesma aparência nos navegadores. Alguma alternativa conhecida?
Josh Mc

6
Versão de linha única da inicialização acima:var d = new Date(Date.UTC(2004,1,29,2,45,26));
m1kael

4
Pode valer a pena considerar que o Chrome (a partir da v35) não leva em consideração a localidade do usuário nas toLocaleString()funções.
benno

8
Sinto muito, mas esse método não funciona abaixo (estou na Austrália), quando executo o código acima, a data é exibida no formato dos EUA. Além disso, o MDN diz 'o código do idioma usado e a forma da string retornada são totalmente dependentes da implementação'.
tgrrr

65

Para novos projetos, basta usar moment.js

Essa pergunta é bastante antiga, então o moment.js não existia naquele momento, mas para novos projetos, simplifica muito essas tarefas.

É melhor analisar sua string de data do UTC da seguinte maneira (crie uma string compatível com ISO-8601 no servidor para obter resultados consistentes em todos os navegadores):

var m = moment("2013-02-08T09:30:26Z");

Agora basta usar mem seu aplicativo, moment.js o padrão para o fuso horário local para operações de exibição. Existem várias maneiras de formatar os valores de data e hora ou extrair partes dele.

Você pode até formatar um objeto de momento no código do idioma dos usuários assim:

m.format('LLL') // Returns "February 8 2013 8:30 AM" on en-us

Para transformar um objeto moment.js em um fuso horário diferente (ou seja, nem o local nem o UTC), você precisará da extensão moment.js . Essa página também tem alguns exemplos, é bem simples de usar.


Como você combina tudo isso? m.utcOffset (offset) .format ('LLL') parece não funcionar.
Bart

Should Luxon ou Day.js ser a biblioteca sugeriu agora?
Homer

1
Sugiro adicionarFor old projects, just use jQuery
Xenos

Não funciona no chrome - ainda mostra am / pm, embora o tempo esteja definido para 24h nas configurações de localidade do computador
vir us

20

Você pode usar new Date().getTimezoneOffset()/60para o fuso horário. Também existe um toLocaleString()método para exibir uma data usando a localidade do usuário.

Aqui está a lista completa: Trabalhando com datas


toLocaleString é extremamente confiável por apresentar datas no formato que o usuário pode esperar. Mesmo onde o ISO 402 é suportado, ele ainda é pouco confiável e baseia o formato em um idioma, não em um local.
RobG

@RobG, qual é a solução em vez de toLocaleString?
user924

@ user924 - você pode usar uma biblioteca, há muito por onde escolher. O problema com toLocaleString é que diferentes implementações fornecem resultados diferentes com diferentes níveis de suporte para vários idiomas e regiões. Por exemplo, o idioma padrão do meu sistema não é en-US, mas o formato padrão para toLocaleString para alguns navegadores é o formato dos EUA, outros respeitam o idioma do meu sistema. É o mesmo com os nomes de fuso horário, apenas pior porque eles não são padronizados. :-(
RobG

7

Depois de criar seu objeto de data, eis um trecho da conversão:

A função pega um objeto Date formatado em UTC e uma string de formato.
Você precisará de um Date.strftimeprotótipo.

function UTCToLocalTimeString(d, format) {
    if (timeOffsetInHours == null) {
        timeOffsetInHours = (new Date().getTimezoneOffset()/60) * (-1);
    }
    d.setHours(d.getHours() + timeOffsetInHours);

    return d.strftime(format);
}

6
de onde você saiu?
Anuj Pandey

A definição das horas tem algum efeito nas partes Dia / Data / Ano de um objeto Data? Não parece.
ChristoKiwi

1
@ ChristoKiwi - espera-se que o valor passado para setHours seja um número inteiro getTimezoneOffset()/60pode retornar uma fração (por exemplo, o deslocamento da Índia de +05: 30 retornará 5,5). Os decimais são truncados. Caso contrário, definir as horas atualiza outros valores (defina as horas para 48 e veja o que acontece).
RobG

7

No JS, não há maneiras simples e de plataforma cruzada para formatar a hora local da data, além da conversão de cada propriedade, conforme mencionado acima.

Aqui está um hack rápido que eu uso para obter o AAAA-MM-DD local. Observe que isso é um hack, pois a data final não terá mais o fuso horário correto (portanto, você deve ignorar o fuso horário). Se eu precisar de mais alguma coisa, uso moment.js.

var d = new Date();    
d = new Date(d.getTime() - d.getTimezoneOffset() * 60000)
var yyyymmdd = t.toISOString().slice(0,0); 
// 2017-05-09T08:24:26.581Z (but this is not UTC)

O d.getTimezoneOffset () retorna o deslocamento do fuso horário em minutos e o d.getTime () está em ms, portanto x 60.000.


1
@VG Adicionei mais algumas informações sobre de onde vem os 60k. Espero que esta ajuda.
Jeremy Chone

5

Aqui está o que eu usei em projetos anteriores:

var myDate = new Date();
var tzo = (myDate.getTimezoneOffset()/60)*(-1);
//get server date value here, the parseInvariant is from MS Ajax, you would need to do something similar on your own
myDate = new Date.parseInvariant('<%=DataCurrentDate%>', 'yyyyMMdd hh:mm:ss');
myDate.setHours(myDate.getHours() + tzo);
//here you would have to get a handle to your span / div to set.  again, I'm using MS Ajax's $get
var dateSpn = $get('dataDate');
dateSpn.innerHTML = myDate.localeFormat('F');

4
Isso ocorre com coisas específicas do ASP.NET.
ZiggyTheHamster

As compensações de fuso horário não são necessariamente múltiplos de uma hora; portanto getTimezoneOffset()/60, geralmente retornam um valor decimal. Isso é particularmente verdadeiro para datas anteriores a 1900, onde muitos lugares tinham compensações em minutos e segundos. Além disso, agora são necessárias datas javascript para oferecer suporte a compensações históricas. Por exemplo, em 1890, a compensação em Moscou foi de +2: 30: 17. Consulte Navegadores, fusos horários, Erro do Chrome 67 .
RobG

3

O .getTimezoneOffset()método relata o deslocamento do fuso horário em minutos, contando "para oeste" a partir do fuso horário GMT / UTC, resultando em um valor de deslocamento negativo para o que normalmente está acostumado. (Por exemplo, o horário de Nova York seria relatado em +240 minutos ou +4 horas)

Para obter um deslocamento normal do fuso horário em horas, você precisa usar:

var timeOffsetInHours = -(new Date()).getTimezoneOffset()/60

Detalhe importante:
Observe que o horário de verão é fatorado no resultado - portanto, o que esse método fornece é realmente o deslocamento de hora - e não o deslocamento geográfico real do fuso horário .


3

Com a data do código PHP eu usei algo como isto ..

function getLocalDate(php_date) {
  var dt = new Date(php_date);
  var minutes = dt.getTimezoneOffset();
  dt = new Date(dt.getTime() + minutes*60000);
  return dt;
}

Podemos chamar assim

var localdateObj = getLocalDate('2015-09-25T02:57:46');

A pergunta era sobre JavaScript, não PHP.
Pipedreambomb

5
A resposta está apenas em javascript, é mencionado em questão que a data do servidor está no UTC. portanto, o servidor pode estar em qualquer idioma. então eu respondi apenas para PHP
hriziya 02/09

3

Eu misturei as respostas até agora e as adicionei, porque tive que ler todas elas e investigar adicionalmente por um tempo para exibir uma sequência de data e hora de db no formato de fuso horário local do usuário.

A string datetime vem de um python / django db no formato: 2016-12-05T15: 12: 24.215Z

A detecção confiável do idioma do navegador em JavaScript parece não funcionar em todos os navegadores (consulte JavaScript para detectar a preferência de idioma do navegador ), por isso recebo o idioma do navegador no servidor.

Python / Django: envie a linguagem do navegador de solicitação como parâmetro de contexto:

language = request.META.get('HTTP_ACCEPT_LANGUAGE')
return render(request, 'cssexy/index.html', { "language": language })

HTML: escreva-o em uma entrada oculta:

<input type="hidden" id="browserlanguage" value={{ language }}/>

JavaScript: obtenha o valor da entrada oculta, por exemplo, en-GB, en-US; q = 0,8, en; q = 0,6 / e, em seguida, pegue o primeiro idioma da lista apenas por meio de substituição e expressão regular

const browserlanguage = document.getElementById("browserlanguage").value;
var defaultlang = browserlanguage.replace(/(\w{2}\-\w{2}),.*/, "$1");

JavaScript: converta para data e hora e formate-o:

var options = { hour: "2-digit", minute: "2-digit" };
var dt = (new Date(str)).toLocaleDateString(defaultlang, options);

Consulte: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

O resultado é (o idioma do navegador é pt-br): 05/12/2016, 14:58


3

// new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
var serverDate = new Date(2018, 5, 30, 19, 13, 15); // just any date that comes from server
var serverDateStr = serverDate.toLocaleString("en-US", {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
})
var userDate = new Date(serverDateStr + " UTC");
var locale = window.navigator.userLanguage || window.navigator.language;

var clientDateStr = userDate.toLocaleString(locale, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric'
});

var clientDateTimeStr = userDate.toLocaleString(locale, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
});

console.log("Server UTC date: " + serverDateStr);
console.log("User's local date: " + clientDateStr);
console.log("User's local date&time: " + clientDateTimeStr);


Para a referência: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... (eu precisava da optionsparte para o meu caso)
Xenos

2

A melhor solução que encontrei é criar [time display = "llll" datetime = "UTC TIME" /] Tags e usar javascript (jquery) para analisar e exibi-lo em relação ao horário do usuário.

http://momentjs.com/ Moment.js

exibirá a hora muito bem.


2

Você pode usar o seguinte, que relata o deslocamento do fuso horário do GMT em minutos:

new Date().getTimezoneOffset();

Nota: - esta função retorna um número negativo.


1

getTimeZoneOffset () e toLocaleString são bons para o trabalho básico de datas, mas se você precisar de suporte real ao fuso horário, consulte o TimeZone.js da mde .

Há mais algumas opções discutidas na resposta a esta pergunta


1

Para converter data em data local, use o método toLocaleDateString ().

var date = (new Date(str)).toLocaleDateString(defaultlang, options);

Para converter a hora em hora local, use o método toLocaleTimeString ().

var time = (new Date(str)).toLocaleTimeString(defaultlang, options);

-12

Não sei como fazer a localidade, mas o javascript é uma tecnologia do lado do cliente.

usersLocalTime = new Date();

terá a hora e a data do cliente (conforme relatado pelo navegador e por extensão do computador em que ele está sentado). Deve ser trivial incluir o tempo do servidor na resposta e fazer algumas contas simples para calcular o deslocamento.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.