在 javascript 中将字符串解析为 Date

Parse string to Date in javascript

本文关键字:Date 字符串 javascript      更新时间:2023-09-26

我正在创建一个函数来比较自定义日期时间和当前日期时间。在比较之前,我将字符串dd/MM/yyyy HH:mm:ss转换为new Date()

这是代码:

var getCurrentDateTime = function () {
	var dt = new Date(),
		dd = dt.getDate(),
		MM = dt.getMonth() + 1,
		yyyy = dt.getFullYear(),
		HH = dt.getHours(),
		mm = dt.getMinutes(),
		ss = dt.getSeconds();
	return new Date(yyyy, MM, dd, HH, mm, ss)
};
var parseTimeString = function (d) {	
 
        // `d` formatting: 'dd/MM/yyyy HH:mm:ss'
	var d_d = d.split(' ')[0],
        	d_t = d.split(' ')[1],
                //x = new Date(2016, 01, 14, 21, 40, 00),
		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]),
		c = getCurrentDateTime(),
		z = Math.abs((c.getTime() - x.getTime())/1000);		
	if (z <= 29) {
		return 'Just now'
	}
	if (z > 29 && z < 60) {
		return '30 seconds ago'
	}
	if (z >= 60 && z < 120) {
		return '1 minute ago'
	}
	if (z >= 120 && z < 3600) {
		return (c.getMinutes() - x.getMinutes()) + ' minutes ago'
	}
	if (z >= 3600 && z < 7200) {
		return '1 hour ago'
	}
	if (z >= 7200 && z < 86400) {
		return (c.getHours() - x.getHours()) + ' hours ago'
	}
	if (z >= 86400 && z < 172800) {
		var m = x.getMinutes();
		return 'Yesterday ' + x.getHours() + ':' + (m < 10 ? '0' + m : m)
	}
	if (z >= 172800) {
		var dd = x.getDate(),
			MM = x.getMonth() + 1,
			yyyy = x.getFullYear(),
			m = x.getMinutes();
		dd = dd < 10 ? '0' + dd : dd;
		MM = MM < 10 ? '0' + MM : MM;
		return dd + '/' + MM + '/' + yyyy + ' at ' + x.getHours() + ':' + (m < 10 ? '0' + m : m)
	}
};
$('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 个间隔,有什么问题吗?(我的网页运行缓慢吗?

首先,正如我在评论中指出的那样,您的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代码高尔夫:

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
    }
}

您的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>

您的代码存在一些问题。正如其他答案中提到的,getCurrentDate 函数不值得拥有,您不妨只做:

new Date();

解析日期时,您不仅需要验证模式,还需要验证值(例如,25:06:63 的时间无效)。您可以将解析和验证捆绑在一个函数中,以便在值无效时返回一个以 NaN 作为时间值的 Date 对象(这是 ECMA-262 所说的)。

此外,在执行"时间前"部分时,您不需要比较的>=部分,因为每个if块都会返回(如案例块)。把它放在一起:

/* 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>