提问人:gggaute 提问时间:3/15/2023 最后编辑:derpirschergggaute 更新时间:3/15/2023 访问量:138
如何在 JavaScript 的 Date 对象数组中找到最早的日期?
How can i find the oldest date in an array of Date objects in JavaScript?
问:
我有一个对应于 Date 对象的字符串数组。喜欢这个:
const timestamps = [
'2023-03-15T10:47:38.878Z',
'2023-03-15T10:46:51.375Z',
'2023-03-15T10:46:39.645Z',
'2023-03-15T10:47:19.072Z',
'2023-03-15T10:46:20.395Z'
]
var convertedTimestamps = [];
for (var time in timestamps) {
var timeAsDate = Date.parse(time);
console.log(time, timeAsDate);
convertedTimestamps.push(timeAsDate);
}
const min = Math.min(...convertedTimestamps);
它们是出于其他目的解析为字符串的 Date 对象 这可以是任何长度,这只是其中的一个实例。我想找到最早的时间戳。
在上面的示例中,这些是转换后的时间戳,最小值基于数字是正确的,但不是日期对象。最上面的一个是被删除的那个
946681200000
978303600000
980982000000
983401200000
986076000000
min: 946681200000
'2023-03-15T10:47:38.878Z'
这可能只是一个数学问题,但按照我的理解,像这样解析的字符串会返回一个 int,表示自 1970 年以来已经过去了多少时间等,所以最古老的应该最接近那个时间,不是吗?此最小值实际上是最新的时间戳。当我尝试最大值时,它也是不正确的。
答:
0赞
41 72 6c
3/15/2023
#1
认为您可以通过调整您的案例中的循环来解决这个问题。循环应如下所示:
for (var i = 0; i < timestamps.length; i++) {
var timeAsDate = Date.parse(timestamps[i]); # just adapted this to the loop
...
}
这应该适合您的情况,因为 before 循环遍历数组的键而不是元素本身,这会导致不正确的 Date 解析,因为它在这种情况下会尝试解析索引而不是时间戳。
评论
0赞
derpirscher
3/15/2023
虽然这个答案解决了问题,但你还应该说明为什么在这里使用循环是错误的......(或者只是将其作为副本关闭)for .. in
0赞
41 72 6c
3/15/2023
@derpirscher感谢您的提示!刚刚编辑了我的答案。
0赞
derpirscher
3/15/2023
但是你的解释是错误的。循环不会遍历数组的元素(如果是,OP 的代码会起作用),而是遍历对象的键,即 OP 的代码获取值,,,,这显然是错误的for .. in
time
"0"
"1"
"2"
"3"
"4"
0赞
41 72 6c
3/15/2023
误会了。索引的含义是,循环正在迭代对象属性,在数组的情况下,该属性将是索引(键)而不是元素。
0赞
0stone0
3/15/2023
#2
由于您正在处理 ISO 8601 时间戳,因此您可以将任何字符串与它进行比较
- 设置为 ,一个高值字符串
lowest
a
- 循环
timestamps
- 如果电流较低,则覆盖
- 日志
const timestamps = [
'2023-03-15T10:47:38.878Z',
'2023-03-15T10:46:51.375Z',
'2023-03-15T10:46:39.645Z',
'2023-03-15T10:47:19.072Z',
'2023-03-15T10:46:20.395Z'
];
let lowest = 'a';
for (let timestamp of timestamps) {
if (lowest > timestamp) {
lowest = timestamp;
}
}
console.log('Lowest timestamp: ' + lowest)
// Lowest timestamp: 2023-03-15T10:46:20.395Z
有用的读物:
评论
1赞
derpirscher
3/15/2023
实际上,使用 ISO 时间戳,无需解析。你可以通过字符串比较来比较它们。而且,使用类似 的值初始化 也会更有效,您不需要在每次迭代中检查。lower
Number.MAX_SAFE_INTEGER
0
1赞
derpirscher
3/15/2023
对不起,如果我的评论不清楚,但以您的使用,这段代码工作纯属巧合,因为......如果是呢?我的意思是,如果您按数值进行比较(即解析),请用 .如果作为字符串进行比较,只需使用或完全确定(如果您必须处理 9999 年)MAX_SAFE_INTEGER.ToString()
MAX_SAFE_INTEGER
9007199254740991
19007199254740991
MAX_SAFE_INTEGER
let lower = '9'
let lower = 'a'
0赞
boppy
3/15/2023
#3
如果所有日期都遵循上述格式,则对该数组进行字符串排序并获取第一个条目就足够了,因为字符串是从最长时间单位到最短时间单位“排序”的。
因此,要获取最早的条目:
const timestamps = [
'2023-03-15T10:47:38.878Z',
'2023-03-15T10:46:51.375Z',
'2023-03-15T10:46:39.645Z',
'2023-03-15T10:47:19.072Z',
'2023-03-15T10:46:20.395Z'
];
const lowest = timestamps.sort()[0];
评论
0赞
InSync
3/15/2023
致读者:请注意,的时间复杂度是 ,而简单循环的时间复杂度是 。.sort
O(n log n)
O(n)
0赞
derpirscher
3/15/2023
排序以查找最大值/最小值是将任务转换为 。可能与小型数据集无关,但仍然不是最佳实践......O(n)
O(n logn)
0赞
boppy
3/15/2023
问题是,这是否会导致更长的运行时间,因为我认为可能比上述自我实现的排序更快(更好地优化)。而且肯定比将每个条目单独解析为 Date-object 要快.......sort
0赞
derpirscher
3/15/2023
无需“排序”。只需遍历集合一次,并记住当前最小的元素。这肯定比任何(即使内置和优化)排序算法都快......
0赞
rjax
3/15/2023
#4
为。。in 用于循环访问对象的属性,而不是数组。如果在循环中添加 console.log(time),您将看到 time 是一个字符串,表示数组的每个索引。如果更改为 for..你的代码将起作用。
const timestamps = [
'2023-03-15T10:47:38.878Z',
'2023-03-15T10:46:51.375Z',
'2023-03-15T10:46:39.645Z',
'2023-03-15T10:47:19.072Z',
'2023-03-15T10:46:20.395Z'
]
for (var time in timestamps) {
console.log(time);
}
for (var time of timestamps) {
console.log(time);
}
此外,除非您需要转换时间戳来做其他事情,否则您可能只想在循环中获取最小值。
const timestamps = [
'2023-03-15T10:47:38.878Z',
'2023-03-15T10:46:51.375Z',
'2023-03-15T10:46:39.645Z',
'2023-03-15T10:47:19.072Z',
'2023-03-15T10:46:20.395Z'
];
let dateTime;
let minDateTime = Date.parse(timestamps[0]);
for (var time of timestamps) {
dateTime = Date.parse(time);
if (dateTime < minDateTime)
minDateTime = dateTime;
}
console.log((new Date(minDateTime)).toISOString());
评论
0赞
derpirscher
3/15/2023
你必须小心你的初始化,如果数组是空的,你的代码会抛出一个错误......let minDateTime = Date.parse(timestamps[0]);
timestamps
评论
time
for .. of
for .. in