0

I have an array of strings corresponding to Date objects. like this:

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);

They are Date objects parsed into strings for other purposes This can be any length really, this is just one instance of it. I want to find the oldest of the timestamps.

In the example above, these are the converted timestamps, and the min value is correct based on the numbers, but not the date objects. The top one is the one that is removed

946681200000
978303600000
980982000000
983401200000
986076000000
min: 946681200000
'2023-03-15T10:47:38.878Z'

It might just be a math problem, but the way i understand it, a string parsed like this returns an int representing how much time has passed since 1970 etc, and so the oldest should be closest to that time should it not? this min value is in fact the most recent of the timestamps. When i try the max value it is not correct either.

2
  • Does this answer your question? Loop (for each) over an array in JavaScript Commented Mar 15, 2023 at 11:43
  • I converted your script into a runable example. Have a look what values time actually has and what is parsed to a date. Use a for .. of loop instead of a for .. in. Otherwise your code is fine ... Commented Mar 15, 2023 at 11:44

4 Answers 4

0

If all dates are following the format mentioned, it's enough to string-sort that array and get the first entry, since the string is "sorted" from longest time-unit to shortest.

So to get the oldest entry:

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];
Sign up to request clarification or add additional context in comments.

4 Comments

To readers: Note that .sort's time complexity is O(n log n) while that of a simple loop is O(n).
Sorting to find the maximum/minimum is turing an O(n) task into O(n logn). May not be relevant for small datasets, but still not best practice ...
Question is, if that results in longer runtime, since I think .sort might be faster (better optimized) than a self-implemented sort as mentioned. And will surely be faster than parsing each entry on its own to a Date-object...
There is no "sorting" necessary. Just iterate over the collection once and remember the current smallest element. This surely is faster than any (even if builtin and optimized) sorting algorithm ...
0

Think you can solve this problem by adapting the loop in your case. The loop should look like this:

for (var i = 0; i < timestamps.length; i++) {
    var timeAsDate = Date.parse(timestamps[i]); # just adapted this to the loop
    ...
}

This should do the work for your case since the the loop before iterates over the keys of the array rather than the elements themselves which leads to a incorrect Date parsing because it tries to parse the index instead of the timestamp in that case.

3 Comments

While that answer solves the problem, you should also state why using a for .. in loop is wrong here ... (or just close it as a duplicate)
But your explanation is wrong. A for .. in loop does not iterate over the elements of an array (if it was, OP's code would work), but over the keys of an object, ie the time in OP's code gets the values "0", "1","2","3","4" which is obviously wrong
mistaken that. what is meant with indexes is, that the loop is iterating over an objects property, which in the case of an array would be the indexes (key) and not the elements.
0

Since you're dealing with ISO 8601 timestamps, you can compare any string against it

  1. Set lowest to a, an high value string
  2. Loop over timestamps
  3. If the current on is lower, overwrite
  4. Log

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


Thanks to @Derpirscher for commenting this.


Useful reads:

2 Comments

Actually, with ISO-Timestamps there is no need to parse. you can just compare them by string comparison. And it would also be more efficient to initialize the lower with a value like Number.MAX_SAFE_INTEGER, you you won't need to check for 0 in every iteration.
Sorry if my comment was unclear, but with your usage of MAX_SAFE_INTEGER.ToString() it's just pure coincidence that this code works, because MAX_SAFE_INTEGER is 9007199254740991 ... What if it was 19007199254740991? I meant if you compare by numeric value (ie with parsing) initialize it with MAX_SAFE_INTEGER. If you compare as string, just use let lower = '9' or to be completely sure (if you have to deal with year 9999) let lower = 'a'
0

for..in is used to iterate over the properties of an object, not an array. If you add console.log(time) in your loop you will see that time is a string representing each index of the array. If you change to for..of your code will work.

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

Also, unless you need the convert timestamps for something else, you might want to simply get the minimum in your loop.

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());

1 Comment

You have to be a bit careful with your initialization of let minDateTime = Date.parse(timestamps[0]); Your code will throw an error if the timestamps array is empty ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.