Data inválida no safari

155
 alert(new Date('2010-11-29'));

chrome, ff não tem problemas com isso, mas o safari grita "data inválida". Por quê ?

edit: ok, conforme os comentários abaixo, usei a análise de string e tentei o seguinte:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

editar 22 de março de 2018 : Parece que as pessoas ainda estão chegando aqui - Hoje, eu usaria momentou acabaria date-fnscom isso. Date-fns é muito livre de dor e leve também.

Shrinath
fonte
Apenas para outros que olham para o mesmo problema: acabei usando o DateJS, que resolveu meu problema em geral. Consulte a resposta aceita para obter detalhes.
Shrinath
2
use moment.js para analisar o registro de data e hora. Especialmente quando se lida com cruz web plataforma
Ming Yuen
1
Esta é uma pergunta antiga. No ECMAScript 2015, as cadeias de data somente ISO 8601 são analisadas como UTC. No entanto, ainda pode haver navegadores mais antigos que não o analisem nem o tratem como local.
`` #

Respostas:

167

O padrão yyyy-MM-ddnão é um formato oficialmente suportado para o Dateconstrutor. O Firefox parece suportá-lo, mas não conte com outros navegadores fazendo o mesmo.

Aqui estão algumas seqüências suportadas:

  • MM-dd-aaaa
  • aaaa / MM / dd
  • MM / dd / aaaa
  • Dd MMMM, aaaa
  • MMM dd, aaaa

O DateJS parece ser uma boa biblioteca para analisar formatos de data não padrão.

Edit : acabou de verificar o padrão ECMA-262 . Citando a seção 15.9.1.15:

Data Hora Formato da sequência

O ECMAScript define um formato de intercâmbio de strings para data e hora com base na simplificação do formato estendido ISO 8601. O formato é o seguinte: AAAA-MM-DDTHH: mm: ss.sssZ Onde os campos são os seguintes:

  • AAAA são os dígitos decimais do ano no calendário gregoriano.
  • "-" (hífon) aparece literalmente duas vezes na string.
  • MM é o mês do ano de 01 (janeiro) a 12 (dezembro).
  • DD é o dia do mês de 01 a 31.
  • "T" aparece literalmente na string, para indicar o início do elemento time.
  • HH é o número de horas completas que passaram desde a meia-noite como dois dígitos decimais.
  • ":" (dois pontos) aparece literalmente duas vezes na string.
  • mm é o número de minutos completos desde o início da hora como dois dígitos decimais.
  • ss é o número de segundos completos desde o início do minuto como dois dígitos decimais.
  • "." (ponto) aparece literalmente na string.
  • sss é o número de milissegundos completos desde o início do segundo como três dígitos decimais. Tanto o "." e o campo de milissegundos pode ser omitido.
  • Z é o deslocamento do fuso horário especificado como "Z" (para UTC) ou "+" ou "-" seguido de uma expressão de hora hh: mm

Este formato inclui formulários somente para data:

  • AAAA
  • AAAA-MM
  • AAAA-MM-DD

Ele também inclui formulários somente de hora com um deslocamento de fuso horário opcional anexado:

  • THH: mm
  • THH: mm: ss
  • THH: mm: ss.sss

Também estão incluídas as "datas e horários", que podem ser qualquer combinação dos itens acima.

Portanto, parece que AAAA-MM-DD está incluído no padrão, mas, por alguma razão, o Safari não é compatível.

Atualização : após examinar a documentação do datejs , utilizá-lo, seu problema deve ser resolvido usando um código como este:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");
darioo
fonte
4
O formato ISO8601 é usado na 5ª edição do padrão ECMAScript, e ainda não é amplamente suportado, a maneira mais segura de obter IMO, analisar a data manualmente :(
CMS
1
Isso foi muito útil, cara .. Obrigado .. :) Finalmente, acabei usando o datejs para formatar.
Shrinath
para aqueles no futuro, observe que, embora o datejs seja fantástico na maioria dos aspectos, ele não resolve todos os problemas de formatação de data, principalmente no safari. é uma PITA, mas é melhor fazê-lo manualmente se você ainda tiver problemas.
totallyNotLizards
@darioo Então, tentei sua resposta da seguinte forma: "var start = Date.parseExact (carimbo de data / hora," AAAA-DD-MM HH: mm: SS ");" o carimbo de data e hora é "2016-01-28 00:00:00". No entanto, agora eu recebo o erro, que "Date.parseExact não é uma função". Você sabe o que está acontecendo aqui?
threxx
5
Meu problema semelhante foi causado pelo Safari não saber ler o fuso horário no formato de fuso horário RFC 822. Consegui consertar isso usando o formato ISO 8601. Se você tem o controle do formato da data, consegui trabalhar com "aaaa-MM-dd'T'HH: mm: ss.sssXXX", que cria ie. "2018-02-06T20: 00: 00.000 + 00: 00". Por qualquer motivo, o Safari não pode ler "2018-02-06T20: 00: 00.000 + 0000", observe a falta de dois pontos no formato de fuso horário.
Olmstov 6/03/19
224

Para mim, implementar uma nova biblioteca apenas porque o Safari não pode fazê-lo corretamente é demais e um regex é um exagero. Aqui está o oneliner :

console.log (new Date('2011-04-12'.replace(/-/g, "/")));
Elzo Valugi
fonte
Se receber uma barra fosse apenas o meu problema, eu teria "aceito" sua resposta (embora esse fosse meu único objetivo quando fiz essa pergunta). Agora que encontrei o dateJS, implementei o formato MMM DD, AAAA para uma experiência mais amigável !!!
quer
13
Esta ajuda de uma linha foi perfeita para a minha necessidade! Obrigado!
Cyril N.
4
Isso foi bastante simples para mim também. Não posso acreditar que o Safari não gosta do - mas o mesmo formato com a \\ funciona. Obrigado @Elzo e obrigado Shrinath por postar a pergunta
Pete
1
Eu acho que esta é a melhor resposta que eu tendem a esquecer / - / g em vez de '-' #
1111 Jacek Pietal 10/10
12
aplausos por não implementar uma biblioteca.
Lharby
56

Eu estava enfrentando um problema semelhante. Date.Parse("DATESTRING")estava trabalhando no Chrome (versão 59.0.3071.115), mas não no Safari (versão 10.1.1 (11603.2.5))

Safári:

Date.parse("2017-01-22 11:57:00")
NaN

Cromada:

Date.parse("2017-01-22 11:57:00")
1485115020000

A solução que funcionou para mim foi substituir o espaço no dateString por "T". (exemplo dateString.replace(/ /g,"T"):)

Safári:

Date.parse("2017-01-22T11:57:00")
1485086220000

Cromada:

Date.parse("2017-01-22T11:57:00")
1485115020000

Observe que a resposta do navegador Safari é 8 horas (28800000ms) menor que a resposta vista no navegador Chrome porque o Safari retornou a resposta na TZ local (que fica 8 horas atrás do UTC)

Para obter os dois tempos no mesmo TZ

Safári:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Cromada:

Date.parse("2017-01-22T11:57:00Z")
1485086220000
nizantz
fonte
Ou, se as duas datas não forem iguais no Safari e no Chrome, você poderá usar o new Date(year, month, date, hours, minutes, seconds, milliseconds)construtor. Analise a data da string com uma matriz de seus componentes para usar esses componentes no construtor. @ Nizantz, seria ótimo se você acha que esse exemplo pode ser adicionado à sua resposta.
H3dkandi
Não é particularmente útil, pois você obtém a data no UTC e não a hora local.
Jonas Äppelgran
1
Essa dateString.replace(/ /g,"T")linha mágica de código funcionou de mim. :)
Mazdak Shojaie
substituir (/ - / g, '/')
Jack Hu
11

Eu uso o momento para resolver o problema. Por exemplo

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();
liwp_Stephen
fonte
10

Para ter uma solução funcionando na maioria dos navegadores, você deve criar seu objeto de data com este formato

(year, month, date, hours, minutes, seconds, ms)

por exemplo:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

funciona bem com IE, FF, Chrome e Safari. Versões ainda mais antigas.

IE Dev Center: objeto de data (JavaScript)

Rede de Desenvolvimento Mozilla: Data

Luxx
fonte
6

converter string em data fromat (você precisa conhecer o fuso horário do servidor)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

onde +08: 00 = fuso horário do servidor

Anja Ishmukhametova
fonte
Isso não leva em consideração o horário de verão. O deslocamento da TZ pode variar e depende da própria data (e hora).
costa
5

Eu tive o mesmo problema.Em seguida, usei o momento.Js . O problema desapareceu.

Ao criar um momento a partir de uma sequência, primeiro verificamos se a sequência corresponde aos formatos ISO 8601 conhecidos e, em seguida, retornamos à nova Data (sequência) se um formato conhecido não for encontrado.

Aviso: O suporte do navegador para analisar seqüências de caracteres é inconsistente. Como não há especificação sobre quais formatos devem ser suportados, o que funciona em alguns navegadores não funcionará em outros navegadores.

Para resultados consistentes analisando qualquer coisa que não seja ISO 8601, você deve usar String + Format.

por exemplo

var date= moment(String);
Sampath
fonte
3

Embora você possa esperar que os navegadores suportem a ISO 8601 (ou subconjuntos somente de data), esse não é o caso. Todos os navegadores que eu conheço (pelo menos nos locais dos EUA / inglês que eu uso) são capazes de analisar o horrível MM/DD/YYYYformato dos EUA .

Se você já possui as partes da data, tente usar Date.UTC () . Se não, mas você deve usar o YYYY-MM-DDformato, sugiro usar uma expressão regular para analisar as peças que você conhece e depois passá-las para Date.UTC().

Phrogz
fonte
Eu acho que a análise de cordas é o caminho a seguir :(
Shrinath 30/11
1

Use o formato abaixo, ele funcionaria em todos os navegadores

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

// Sua saída ficaria assim "Qua 23 de março de 2016 00:00:00 GMT + 0530 (IST)"

// Observe que este estaria no fuso horário atual, neste caso indicado pelo IST, para converter para o fuso horário UTC, você pode incluir

alert(dateObj.toUTCSting);

// Sua saída agora gostaria desta "ter, 22 de março de 2016 18:30:00 GMT"

Observe que agora o dateObj mostra a hora no formato GMT, observe também que a data e a hora foram alteradas correspondentemente.

A função "toUTCSting" recupera o horário correspondente no meridiano de Greenwich. Isso é feito estabelecendo a diferença horária entre o fuso horário atual e o fuso horário do Meridiano de Greenwich.

No caso acima, o tempo antes da conversão era 00:00 horas e minutos em 23 de março do ano de 2016. E após a conversão das horas GMT + 0530 (IST) para GMT (subtrai basicamente 5,30 horas do carimbo de data / hora especificado neste caso) o tempo reflete 18,30 horas em 22 de março do ano de 2016 (exatamente 5,30 horas antes da primeira vez).

Além disso, para converter qualquer objeto de data em carimbo de data / hora, você pode usar

alert(dateObj.getTime());

// saída seria algo semelhante a este "1458671400000"

Isso daria a você o carimbo de data e hora exclusivo

Abhay Aradhya
fonte
1

Que tal seqüestrar Datecom data fixa ? Sem dependências, min + gzip = 280 B

Kenberkeley
fonte
1

A melhor maneira de fazer isso é usando o seguinte formato:

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

Isso é suportado em todos os navegadores e não oferece nenhum problema. Observe que os meses são gravados de 0 a 11.

Daniël Brito
fonte
Funciona bem no Safari e Chrome, mas ainda tem problemas no Firefox. Safari: var date = new Data (2018,06,08,19,17) Dom Jul 08 2018 19:17:00 GMT + 0800 (+08) Chrome: var date = new Data (2018,06,08,19, 17) Sun 08 de julho de 2018 19:17:00 GMT + 0800 (Tempo Malásia) Firefox: data de var = new Date (2018,06,08,19,17) data 2018-07-08T11: 17: 00.000Z
Biranchi
0

O mesmo problema enfrentado no Safari e foi resolvido inserindo-o na página da web

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

Espero que também funcione no seu caso

obrigado

Yasir Shabbir Choudhary
fonte
Por que você acha que isso funcionaria? Eu olhei para o script e ele não parece substituir os métodos no objeto Date. Eu fui aqui: polyfill.io/v3/url-builder e parece não haver nada sobre a análise de datas.
costa
0

Como o @nizantz mencionou anteriormente, o uso do Date.parse () não estava funcionando para mim no Safari. Após algumas pesquisas, soube que a propriedade lastDateModified para o objeto File foi preterida e não é mais suportada pelo Safari. O uso da propriedade lastModified do objeto File resolveu meus problemas. Certamente não gosto quando informações ruins são encontradas online.

Obrigado a todos que contribuíram para este post que me ajudaram a seguir o caminho que eu precisava para aprender sobre o meu problema. Se não fosse por essa informação, eu provavelmente nunca teria descoberto meu problema raiz. Talvez isso ajude alguém na minha situação semelhante.

S. Costello
fonte
0

Também estou enfrentando o mesmo problema no Safari Browser

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

Aqui a solução:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 
venkatskpi
fonte
0

Esta não é a melhor solução, embora eu simplesmente pegue o erro e envie a data atual. Pessoalmente, sinto que não estou resolvendo problemas do Safari, se os usuários quiserem usar um navegador que não seja compatível com os padrões * - eles precisam conviver com peculiaridades.

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

Sugiro que seu back-end envie datas ISO.

AndrewMcLagan
fonte
Com todo o respeito, quando você quer dizer que os usuários precisam usar o navegador para o qual você escreveu o código, isso parece ruim no sentido geral. Também depende de nossos casos de uso e público-alvo - se um site estiver sendo construído para o consumo do mercado de massa, também estaremos apoiando o IE10, no mínimo. Tenho certeza de que alguém no MS pensou o mesmo quando estava projetando / codificando para o Internet Explorer. Todos sabemos como se fala agora.
Shrinath
-1

use o formato 'mm / dd / aaaa'. Por exemplo: - nova data ('02 / 28/2015 '). Funciona bem em todos os navegadores.

Ravi S
fonte