Конструктор дати повертає NaN в IE, але працює у Firefox та Chrome


79

Я намагаюся створити невеликий календар у JavaScript. У мене дати чудово працюють у Firefox та Chrome, але в IE функції дати повертають NaN.

Ось функція:

function buildWeek(dateText){
    var headerDates='';
    var newDate = new Date(dateText);

    for(var d=0;d<7;d++){
        headerDates += '<th>' + newDate + '</th>';
        newDate.setDate(newDate.getDate()+1);
    }                       

    jQuery('div#headerDates').html('<table><tr>'+headerDates+'</tr></table>');
}

dateTextце понеділок поточного тижня, який фактично встановлений у php у форматі 'm, d, Y', наприклад "02, 01, 2010".


2
У вас є деякі помилки копіювання-вставки у зразку коду, подивіться на твердження: for(var d=0;d';це призведе до SyntaxError...
Крістіан С. Сальвадо

Відповіді:


67

Конструктор Date приймає будь-яке значення. Якщо примітив [[значення]] аргументу є числом, тоді Дата, яка створена, має це значення. Якщо примітивним [[значення]] є String, тоді специфікація гарантує лише те, що конструктор Date і метод синтаксичного аналізу здатні аналізувати результат Date.prototype.toString і Date.prototype.toUTCString ()

Надійним способом встановлення дати є побудова дати та використання методів setFullYearі setTime.

Приклад цього наведено тут: http://jibbering.com/faq/#parseDate

ECMA-262 r3 не визначає жодних форматів дат. Передача рядкових значень конструктору Date або Date.parse має результат, який залежить від реалізації. Краще уникати.


Редагувати: Запис із розділу поширених запитань comp.lang.javascript є: Розширений локальний формат дати ISO 8601 YYYY-MM-DDможе бути проаналізований на Dateтакий:

/**Parses string formatted as YYYY-MM-DD to a Date object.
 * If the supplied string does not match the format, an 
 * invalid Date (value NaN) is returned.
 * @param {string} dateStringInRange format YYYY-MM-DD, with year in
 * range of 0000-9999, inclusive.
 * @return {Date} Date object representing the string.
 */

  function parseISO8601(dateStringInRange) {
    var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/,
        date = new Date(NaN), month,
        parts = isoExp.exec(dateStringInRange);

    if(parts) {
      month = +parts[2];
      date.setFullYear(parts[1], month - 1, parts[3]);
      if(month != date.getMonth() + 1) {
        date.setTime(NaN);
      }
    }
    return date;
  }

Дякую, Гаррет. Ця функція, яку ви надали за посиланням, найкраща набагато стисліша, ніж будь-що інше, що мені вдалося знайти, і вона працює з форматом дати, який я використовую в інших 99% програми! Набагато більш послідовний, ніж те, що я використовував.
педальпет

Це, на жаль, не добре, оскільки багато структурованих форматів просто використовують формати дати / часу W3C (ISO-8601 із повними специфікаціями або близько того). Отож, хоча мітки часу в багатьох відношеннях є кращими (простішими, ефективнішими, працюють з усіма браузерами), часто потрібно, щоб стандартні дані дати та часу були проаналізовані з javascript. Цікаво, чи б jQuery чи подібні мали кращі методи аналізу.
StaxMan

3
спасибі за вказівку, божевоління, чому chrome чудово аналізує дати, тоді як ie7 каже NAN, добре $ .datepicker.parseDate з jquery вміє аналізувати дати
Carlos Jaime C. De Leon

Що робити, якщо ви теж хочете мілісекунд?
okysabeni

Я використовував функцію, яка була отримана з цього коду, щоб проаналізувати дату / час ISO із рядка. У рідкісних випадках у if (month != date.getMonth() + 1)заяву вводитимуть, здавалося б, дійсне значення, недійсне дату. Наприклад, 2014-06-01T01:09:22.68. Чи можете ви пояснити мету цього ifтвердження?
Грінн

87

З формату дати / часу mysql:

var dateStr="2011-08-03 09:15:11"; //returned from mysql timestamp/datetime field
var a=dateStr.split(" ");
var d=a[0].split("-");
var t=a[1].split(":");
var date = new Date(d[0],(d[1]-1),d[2],t[0],t[1],t[2]);

Сподіваюсь, комусь корисно. Працює в IE FF Chrome


Працює з усіма браузерами. Thnx
Tejas

1
const a = dateStr.split(' '); const d = a[0].split('-'); const t = a[1].split(':'); currentValue.created_date = new Date(+d[0], (+d[1] - 1), +d[2], +t[0], +t[1]);для ES5 або вище.
Sydwell

15

Не використовуйте "new Date ()", оскільки вхідний рядок дати приймається як місцевий час:

new Date('11/08/2010').getTime()-new Date('11/07/2010').getTime();  //90000000
new Date('11/07/2010').getTime()-new Date('11/06/2010').getTime();  //86400000

ми повинні використовувати "NewDate ()", це приймає введення як час GMT:

function NewDate(str)
         {str=str.split('-');
          var date=new Date();
          date.setUTCFullYear(str[0], str[1]-1, str[2]);
          date.setUTCHours(0, 0, 0, 0);
          return date;
         }
NewDate('2010-11-07').toGMTString();
NewDate('2010-11-08').toGMTString();

7

Ось ще один підхід, який додає метод до Dateоб’єкта

використання: var d = (new Date()).parseISO8601("1971-12-15");

    / **
     * Аналізує сформовану дату ISO 8601 на об'єкт дати, ISO 8601 - РРРР-ММ-ДД
     * 
     * @param {String} дату датою у вигляді рядка, наприклад 1971-12-15
     * @returns {Дата} Об'єкт дати, що представляє дату наданого рядка
     * /
    Date.prototype.parseISO8601 = функція (дата) {
        var збіги = date.match (/ ^ \ s * (\ d {4}) - (\ d {2}) - (\ d {2}) \ s * $ /);

        якщо (збігається) {
            this.setFullYear (parseInt (збіги [1]));    
            this.setMonth (parseInt (збіги [2]) - 1);    
            this.setDate (parseInt (збіги [3]));    
        }

        повернути це;
    };

2

Я завжди зберігаю свою дату за часом UTC.

Це моя власна функція, створена з різних функцій, які я знайшов на цій сторінці.

Потрібно STRING як формат mysql DATETIME (приклад: 2013-06-15 15:21:41). Перевірка за допомогою регулярного виразу необов’язкова. Ви можете видалити цю частину, щоб покращити продуктивність.

Ця функція повертає мітку часу.

DATETIME вважається датою UTC . Будьте обережні: якщо ви очікуєте місцевого часу, ця функція не для вас.

    function datetimeToTimestamp(datetime)
    {
        var regDatetime = /^[0-9]{4}-(?:[0]?[0-9]{1}|10|11|12)-(?:[012]?[0-9]{1}|30|31)(?: (?:[01]?[0-9]{1}|20|21|22|23)(?::[0-5]?[0-9]{1})?(?::[0-5]?[0-9]{1})?)?$/;
        if(regDatetime.test(datetime) === false)
            throw("Wrong format for the param. `Y-m-d H:i:s` expected.");

        var a=datetime.split(" ");
        var d=a[0].split("-");
        var t=a[1].split(":");

        var date = new Date();
        date.setUTCFullYear(d[0],(d[1]-1),d[2]);
        date.setUTCHours(t[0],t[1],t[2], 0);

        return date.getTime();
    }

2

Ось фрагмент коду, який виправляє поведінку IE (v ['date'] - це рядок дати, відокремлений комами, наприклад "2010,4,1"):

if($.browser.msie){
    $.lst = v['date'].split(',');
    $.tmp = new Date(parseInt($.lst[0]),parseInt($.lst[1])-1,parseInt($.lst[2]));
} else {
    $.tmp = new Date(v['date']);
}

Попередній підхід не враховував, що місяць JS Date базується на НУЛІ ...

Вибачте, що не пояснив занадто багато, я на роботі і просто думав, що це може допомогти.


1

Ось мій підхід:

var parseDate = function(dateArg) {
    var dateValues = dateArg.split('-');
    var date = new Date(dateValues[0],dateValues[1],dateValues[2]);
    return date.format("m/d/Y");
}

замініть ('-')на використовуваний вами деліметр.


1

Надішліть текст дати та формат, у якому ви надсилаєте текст дати, наведеним нижче способом. Він проаналізує і поверне як дату, і це не залежить від браузера.

function cal_parse_internal(val, format) {
val = val + "";
format = format + "";
var i_val = 0;
var i_format = 0;
var x, y;
var now = new Date(dbSysCurrentDate);
var year = now.getYear();
var month = now.getMonth() + 1;
var date = now.getDate();

while (i_format < format.length) {
    // Get next token from format string
    var c = format.charAt(i_format);
    var token = "";
    while ((format.charAt(i_format) == c) && (i_format < format.length)) {
        token += format.charAt(i_format++);
    }
    // Extract contents of value based on format token
    if (token == "yyyy" || token == "yy" || token == "y") {
        if (token == "yyyy") { x = 4; y = 4; }
        if (token == "yy")   { x = 2; y = 2; }
        if (token == "y")    { x = 2; y = 4; }
        year = _getInt(val, i_val, x, y);
        if (year == null) { return 0; }
        i_val += year.length;
        if (year.length == 2) {
            if (year > 70) {
                year = 1900 + (year - 0);
            } else {
                year = 2000 + (year - 0);
            }
        }
    } else if (token == "MMMM") {
        month = 0;
        for (var i = 0; i < MONTHS_LONG.length; i++) {
            var month_name = MONTHS_LONG[i];
            if (val.substring(i_val, i_val + month_name.length) == month_name) {
                month = i + 1;
                i_val += month_name.length;
                break;
            }
        }
        if (month < 1 || month > 12) { return 0; }
    } else if (token == "MMM") {
        month = 0;
        for (var i = 0; i < MONTHS_SHORT.length; i++) {
            var month_name = MONTHS_SHORT[i];
            if (val.substring(i_val, i_val + month_name.length) == month_name) {
                month = i + 1;
                i_val += month_name.length;
                break;
            }
        }
        if (month < 1 || month > 12) { return 0; }
    } else if (token == "MM" || token == "M") {     
        month = _getInt(val, i_val, token.length, 2);
        if (month == null || month < 1 || month > 12) { return 0; }
        i_val += month.length;
    } else if (token == "dd" || token == "d") {
        date = _getInt(val, i_val, token.length, 2);
        if (date == null || date < 1 || date > 31) { return 0; }
        i_val += date.length;
    } else {
        if (val.substring(i_val, i_val+token.length) != token) {return 0;}
        else {i_val += token.length;}
    }
}

// If there are any trailing characters left in the value, it doesn't match
if (i_val != val.length) { return 0; }

// Is date valid for month?
if (month == 2) {
    // Check for leap year
    if ((year%4 == 0 && year%100 != 0) || (year%400 == 0)) { // leap year
        if (date > 29) { return false; }
    } else {
        if (date > 28) { return false; }
    }
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
    if (date > 30) { return false; }
}
return new Date(year, month - 1, date);
}

Дякую Валлі. Я відповів на відповідь Гаррета нижче, оскільки функція, до якої він зв’язаний, була меншою, і я працював із форматом дати, який я регулярно використовую.
педальпет

0

Конструктору Date в JavaScript потрібен рядок в одному з форматів дати, що підтримується методом parse ().

Очевидно, формат, який ви вказуєте, не підтримується в IE, тому вам доведеться або змінити код PHP, або проаналізувати рядок вручну в JavaScript.


4
Це досить очевидно, але було б добре знати, якими можуть бути підтримувані формати ...
StaxMan

0

Для аналізу рядка дати ISO8601 можна використовувати такий код:

function parseISO8601(d) {
    var timestamp = d;
    if (typeof (d) !== 'number') {
        timestamp = Date.parse(d);
    }
    return new Date(timestamp);
};

0

Спробуйте за допомогою getDateфункції datepicker.

$.datepicker.formatDate('yy-mm-dd',new Date(pField.datepicker("getDate")));

0

Я спробував усі вищезазначені рішення, але у мене нічого не вийшло. Я трохи провів мозковий штурм і виявив це, а також чудово працював у IE11.

value="2020-08-10 05:22:44.0";
var date=new Date(value.replace(" ","T")).$format("d/m/yy h:i:s");
console.log(date);

якщо формат $ не працює для вас, використовуйте лише формат.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.