2016-01-14 3 views
-2

Я создаю функцию для сравнения пользовательских дат с текущими датами. Я конвертирую строку dd/MM/yyyy HH:mm:ss в new Date() перед тем, как сравнивать.Строка parse to Date в javascript

Вот код:

var getCurrentDateTime = function() { 
 
\t var dt = new Date(), 
 
\t \t dd = dt.getDate(), 
 
\t \t MM = dt.getMonth() + 1, 
 
\t \t yyyy = dt.getFullYear(), 
 
\t \t HH = dt.getHours(), 
 
\t \t mm = dt.getMinutes(), 
 
\t \t ss = dt.getSeconds(); 
 

 
\t return new Date(yyyy, MM, dd, HH, mm, ss) 
 
}; 
 

 
var parseTimeString = function (d) { \t 
 
    
 
     // `d` formatting: 'dd/MM/yyyy HH:mm:ss' 
 

 
\t var d_d = d.split(' ')[0], 
 
     \t d_t = d.split(' ')[1], 
 
       //x = new Date(2016, 01, 14, 21, 40, 00), 
 
\t \t x = new Date(+d_d.split('/')[2], +d_d.split('/')[1] - 1, 
 
          +d_d.split('/')[0], +d_t.split(':')[0], 
 
          +d_t.split(':')[1], +d_t.split(':')[2]), 
 
\t \t c = getCurrentDateTime(), 
 
\t \t z = Math.abs((c.getTime() - x.getTime())/1000); \t \t 
 

 
\t if (z <= 29) { 
 
\t \t return 'Just now' 
 
\t } 
 
\t if (z > 29 && z < 60) { 
 
\t \t return '30 seconds ago' 
 
\t } 
 
\t if (z >= 60 && z < 120) { 
 
\t \t return '1 minute ago' 
 
\t } 
 
\t if (z >= 120 && z < 3600) { 
 
\t \t return (c.getMinutes() - x.getMinutes()) + ' minutes ago' 
 
\t } 
 
\t if (z >= 3600 && z < 7200) { 
 
\t \t return '1 hour ago' 
 
\t } 
 
\t if (z >= 7200 && z < 86400) { 
 
\t \t return (c.getHours() - x.getHours()) + ' hours ago' 
 
\t } 
 
\t if (z >= 86400 && z < 172800) { 
 
\t \t var m = x.getMinutes(); 
 
\t \t return 'Yesterday ' + x.getHours() + ':' + (m < 10 ? '0' + m : m) 
 
\t } 
 
\t if (z >= 172800) { 
 
\t \t var dd = x.getDate(), 
 
\t \t \t MM = x.getMonth() + 1, 
 
\t \t \t yyyy = x.getFullYear(), 
 
\t \t \t m = x.getMinutes(); 
 
\t \t dd = dd < 10 ? '0' + dd : dd; 
 
\t \t MM = MM < 10 ? '0' + MM : MM; 
 
\t \t return dd + '/' + MM + '/' + yyyy + ' at ' + x.getHours() + ':' + (m < 10 ? '0' + m : m) 
 
\t } 
 
}; 
 

 
$('button').click(function() { 
 
    setInterval(function() { 
 
    var x = parseTimeString('14/01/2016 21:40:00'); 
 
    $('body').html($('<p>').text(x)) 
 
    }, 1000) 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button>Click me</button>

Моей проблема:

Линии

x = new Date(+d_d.split('/')[2], +d_d.split('/')[1] - 1, 
      +d_d.split('/')[0], +d_t.split(':')[0], 
      +d_t.split(':')[1], +d_t.split(':')[2]) 

не преобразуются в new Date() правильно. Текущая дата-время: 2016/01/14 21:40:00, но напечатанное 14/01/2016 at 21:40 вместо Just now

Чтобы снова проверить, я заменил эту строку в

x = new Date(2016, 01, 14, 21, 40, 00) 

и это прекрасно работает. Итак, почему?

p/s: И мой вопрос: есть ли какие-либо проблемы, если я использую более 20 интервалов за одно и то же время? (Моя веб-страница работает медленно?)

+2

ваш 'getCurrentDateTime()' сломана - он должен просто 'вернуть Date.now()' [не мое вниз голосование, но ИМХО вопрос плохо формируется] – Alnitak

+0

, чтобы отладить, вывести значение 'z' и сообщить нам, что для вас делает – Burki

+1

, он также имеет неправильный' + 1' в месяц, в результате чего ваш расчетный «сейчас» будет составлять один месяц в будущем, что, вероятно, приведет к ваша другая проблема. – Alnitak

ответ

1

Ваша функция getCurrentDateTime была нарушена. Я понятия не имею, почему вы так сильно его скомпрометировали - это всего лишь замена Date, не так ли?

var getCurrentDateTime = function() { 
 
    return new Date(); 
 
}; 
 

 
var parseTimeString = function (d) { 
 
    var dateRegex = /^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})\s+([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})$/; 
 
    var matches = dateRegex.exec(d); 
 
    console.log(matches); 
 
    if(!matches || matches.length<7) 
 
    throw new Error("Invalid date."); 
 
    var givenDate = new Date(1*matches[3], 
 
          1*matches[2]-1, 
 
          1*matches[1], 
 
          1*matches[4], 
 
          1*matches[5], 
 
          1*matches[6]); 
 
    var currentDate = getCurrentDateTime(); 
 
    var difference = Math.abs((currentDate.getTime() - givenDate.getTime())/1000);  
 

 
    if (difference <= 29) { 
 
    return 'Just now' 
 
    } 
 
    if (difference > 29 && difference < 60) { 
 
    return '30 seconds ago' 
 
    } 
 
    if (difference >= 60 && difference < 120) { 
 
    return '1 minute ago' 
 
    } 
 
    if (difference >= 120 && difference < 3600) { 
 
    return (currentDate.getMinutes() - x.getMinutes()) + ' minutes ago' 
 
    } 
 
    if (difference >= 3600 && difference < 7200) { 
 
    return '1 hour ago' 
 
    } 
 
    if (difference >= 7200 && difference < 86400) { 
 
    return (currentDate.getHours() - givenDate.getHours()) + ' hours ago' 
 
    } 
 
    if (difference >= 86400 && difference < 172800) { 
 
    var m = givenDate.getMinutes(); 
 
    return 'Yesterday ' + givenDate.getHours() + ':' + (m < 10 ? '0' + m : m) 
 
    } 
 
    if (difference >= 172800) { 
 
    var dd = givenDate.getDate(), 
 
     MM = givenDate.getMonth() + 1, 
 
     yyyy = givenDate.getFullYear(), 
 
     m = givenDate.getMinutes(); 
 
    dd = dd < 10 ? '0' + dd : dd; 
 
    MM = MM < 10 ? '0' + MM : MM; 
 
    return dd + '/' + MM + '/' + yyyy + ' at ' + givenDate.getHours() + ':' + (m < 10 ? '0' + m : m) 
 
    } 
 
}; 
 

 

 

 
$('button').click(function() { 
 
    var starttime = new Date(); 
 
    var asString = "14/01/2016 "+starttime.getHours()+":"+starttime.getMinutes()+":"+starttime.getSeconds(); 
 
    setInterval(showDate, 1000, asString); 
 
    function showDate(startDate) { 
 
    var x = parseTimeString(startDate); 
 
    $('body').html($('<p>').text(x)) 
 
    } 
 
    showDate(asString); 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button>Click me</button>

+0

Вы читали комментарии, где я указал это? – Alnitak

+0

Когда я использую символ '+', я имею в виду: попробуйте преобразовать 'd_d.split ('/') [2]' в число. И, как вы можете видеть, это неправильно, без каких-либо проблем. –

+0

@ Алнитак Вы сказали: я нашел проблему здесь, здесь и здесь. Так почему? Я все еще не понимаю, почему. –

2

Во-первых, как я указывал в комментариях, ваша getCurrentDateTime() функция слишком сложна, а также имеет «охлаждает один» ошибка в поле месяца, который, вероятно, отвечает для вашей фактической проблемы:

function getCurrentDateTime() { 
    return new Date(); 
} 

Эта функция теперь настолько тривиальная, что ее не стоит.

Во-вторых, вы должны разделить разборе о дате из последующих битов, которые превращают его в нечто читаемом:

function parseDateTime(s) { 
    var date_time = s.split(' '); 
    var date = date_time[0]; 
    var time = date_time[1]; 
    var dmy = date.split('/').map(Number); 
    var hms = time.split(':').map(Number); 

    return new Date(dmy[2], dmy[1] - 1, dmy[0], hms[0], hms[1], hms[2]); 
} 

или если вы как ES6 Code Golf:

let parseTime=(s)=>new(Function.prototype.bind.apply(Date, 
     s.match(/^(\d\d?)\/(\d\d?)\/(\d{1,4})\s+(\d\d?):(\d\d?):(\d\d?)$/) 
      .map((_,i,a)=>a[i<4?4-i:i]-+(i===2)))) 

и затем:

// 
// pass an already-parsed `Date` object here 
// 
function longAgo(t) { 

    // no need for conversions - subtraction will automatically 
    // call `.getValue()` to get the milliseconds value 
    // 
    // - also no call to 'Math.abs' so that the function works 
    // correctly for future dates 
    var z = (Date.now() - t)/1000; 

    if (z >= 0 && z < 30) { 
     // etc 
    } 
} 
+0

Я думаю, вы знаете, что имена переменных не соответствуют функции 'parseDate' ... –

+0

@ TomášZato oops - yes - thanks – Alnitak

+0

Я попробую еще раз. Большое спасибо! –

1

Есть несколько проблем с вашим кодом. Как уже упоминалось в других ответах, то функция getCurrentDate не стоит того, вы можете также просто сделать:

new Date(); 

При разборе дату, вам нужно проверить больше, чем просто шаблон, вы также должны подтвердите значения (например, время 25:06:63 недействительно).Вы можете связать синтаксический анализ и проверку в одной функции, чтобы, если значения недействительны, вы возвращаете объект Date с NaN в качестве значения времени (что говорит ECMA-262).

Кроме того, при выполнении «время назад» часть, вам не нужно >= часть сравнения, так как каждый , если это блок возвращается (как в случае блока). Полагая, что вместе:

/* Parse string in d/m/y h:m:s format to date 
 
** If date string is invalid date, return Date with time value 
 
** of NaN (per ECMA-262) 
 
** 
 
** @param {string} s - date string in format dd/mm/yyyy hh:mm:ss 
 
** @returns {Date} 
 
*/ 
 
function parseDMYHMS(s) { 
 
    var b = s.split(/\D/); 
 
    var d = new Date(b[2], --b[1], b[0], b[3], b[4], b[5]); 
 
     
 
    // Validate the date string components based on the created Date 
 
    return d && d.getMonth() == b[1] && d.getHours() == b[3] && d.getMinutes() == b[4]? d : new Date(NaN); 
 
} 
 

 
/* Return how long ago d was 
 
** 
 
** @param {Date} d 
 
** @returns {string} or undefined if invalid input 
 
*/ 
 
function timeAgo(d) { 
 
    if (!d || !d.getTime()) return; // Deal with falsey input, assume Date otherwise 
 
    function pad(n){return ('0'+n).slice(-2)} 
 
    var z = (new Date() - d)/1e3; // Time difference in seconds 
 
    if (z < 30) return 'Just now'; 
 
    if (z < 60) return '30 seconds ago'; 
 
    if (z < 120) return '1 minute ago'; 
 
    if (z < 3600) return (z/60 | 0) + ' minutes ago'; 
 
    if (z < 7200) return '1 hour ago'; 
 
    if (z < 86400) return (z/3600 | 0) + ' hours ago'; 
 
    if (z < 172800) return 'Yesterday ' + d.getHours() + ':' + pad(d.getMinutes()); 
 
    return pad(d.getDate()) + '/' + pad(d.getMonth()+1) + '/' + d.getFullYear(); 
 
} 
 

 
function showTimeago(s) { 
 
    document.getElementById('div0').innerHTML = timeAgo(parseDMYHMS(s)); 
 
}
<label for="in0">Date (d/m/y h:m:s)<input id="in0" onblur="showTimeago(this.value)" value="14/01/2016 10:03:01"></label> 
 
<br> 
 
<div id="div0"></div>

+0

ya, я забыл конвертировать секунды в минуту. Хорошая точка зрения. Спасибо! –