在javascript中将字符串解析为Date

时间:2016-01-14 14:54:55

标签: javascript date datetime

我创建了一个将自定义日期时间与当前日期时间进行比较的函数。 在比较之前,我将字符串open FSharpx.Control.Observable let foo () = async { use subject = new Subject<int>() subject.OnNext(42) let! x = Async.AwaitObservable subject printfn "Done waiting: %d" x return () } 转换为dd/MM/yyyy HH:mm:ss

以下是代码:

&#13;
&#13;
new Date()
&#13;
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)
})
&#13;
&#13;
&#13;

我的问题:

该行

<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

它完美无缺。那么,为什么?

p / s:我的子问题:如果我在同一时间内使用超过20个间隔,是否有任何问题? (我的网页运行缓慢吗?)

3 个答案:

答案 0 :(得分:2)

首先,正如我在评论中指出的那样,您的getCurrentDateTime()功能过于复杂,并且还有一个&#34;关闭一个&#34;月份字段中的错误,可能是您实际问题的原因:

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

答案 1 :(得分:1)

您的getCurrentDateTime功能已损坏。我不知道为什么你这么复杂 - 它只是Date的替代品,不是吗?

&#13;
&#13;
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);
})
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click me</button>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

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

new Date();

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

此外,在执行“time ago”部分时,您不需要>=部分比较,因为每个 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>