-4

I have an array with a few objects, which is structured like this:

const combined =
{
 id: "1",
 desc: "Description One",
 start: {
         date: "2024-11-01",
        }
},
{
 id: "2",
 desc: "Description Two",
 start: {
         dateTime: "2026-08-13T17:00:00+02:00",
        }
},
{
 id: "3",
 desc: "Description Three",
 start: {
         date: "2023-03-28",
        }
},
{
 id: "4",
 desc: "Description Four",
 start: {
         dateTime: "2026-08-13T15:00:00+02:00",
        }
}

Based on different user input there either is a date date or a date with timestamp dateTime.

Now I want to sort the array based on the earliest date by using the object that exists date or dateTime.

In the given case the correct order should be:

{
 id: "3",
 desc: "Description Three",
 start: {
         date: "2023-03-28",
        }
},
{
 id: "1",
 desc: "Description One",
 start: {
         date: "2024-11-01",
        }
},
{
 id: "4",
 desc: "Description Four",
 start: {
         dateTime: "2026-08-13T15:00:00+02:00",
        }
},
{
 id: "2",
 desc: "Description Two",
 start: {
         dateTime: "2026-08-13T17:00:00+02:00",
        }
}

The earliest date is now [0] and same day dates should be sorted by earliest time.

I tried to use Array.prototype.sort(), but I guess I can't compare the dates in that format.

ZF-Dev
  • 23
  • 6
  • Tried to use it _how_, exactly? Give a [mre]. – jonrsharpe Aug 26 '23 at 15:04
  • If you have dates and times from different timezones, directly comparing them may lead to wrong results, but you can still use `new Date(...).getTime()` to convert them to a unix timestamp which you can compare – derpirscher Aug 26 '23 at 15:05
  • Please visit [help], take [tour] to see what and [ask]. Do some research, search for related topics on SO; if you get stuck, post a [mcve] of your attempt, noting input and expected output, preferably in a [Stacksnippet](https://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) – mplungjan Aug 26 '23 at 15:05
  • Please explain to us if the timezones are the same for all dates and if not, what to do with the dates that do not have timzones? – mplungjan Aug 26 '23 at 18:54

2 Answers2

1

The dates are string comparable without being converted. A localeCompare is enough and you can destruct the object to get at either date or dateTime

I STRONGLY assume same timezone, or this excercise is useless. What are the timezones supposed to be on dates without TZ?

combined.sort((a, b) => {
  const { date: dateA, dateTime: dateTimeA } = a.start;
  const { date: dateB, dateTime: dateTimeB } = b.start;
  return (dateTimeA || dateA).localeCompare(dateTimeB || dateB);
});

console.log(combined);
<script>
const combined = [
  { id: "1", desc: "Description One", start: { date: "2024-11-01" } },
  { id: "2", desc: "Description Two", start: { dateTime: "2026-08-13T17:00:00+02:00" } },
  { id: "3", desc: "Description Three", start: { date: "2023-03-28" } },
  { id: "4", desc: "Description Four", start: { dateTime: "2026-08-13T15:00:00+02:00" } },
];
</script>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • you should parse the timezone, comparing strings doesn't make sense – Alexander Nenashev Aug 26 '23 at 15:21
  • For instance because comparing `2023-08-26` and `2023-08-26T01:00:00+02:00` as strings may lead to undesired results? – derpirscher Aug 26 '23 at 15:26
  • @derpirscher and what can you do about that? That is the input you have. If you do not know the timezone of `2023-08-26`, then it could be the day before or the day after `2023-08-26T01:00:00+02:00` so either we have to assume OR the data has to be more precise. – mplungjan Aug 26 '23 at 18:52
  • You, yourself commented on the question and provided a link to the help center and asked for clarification. So you probably should have waited for an clarification of OP instead of jumping into conclusions ... – derpirscher Aug 26 '23 at 19:46
  • @derpirscher Why should I do that? I answered because I saw others anwer with cumbersome solutions and can correct or delete my answer according to any further information OP will give – mplungjan Aug 26 '23 at 19:49
  • Because for instance, answering based on wrong assumptions (don't know if that's the case here) may lead to wrong answers ... – derpirscher Aug 26 '23 at 19:51
  • Give it a rest, will you! My answer is useful regardless of whether it will give incorrect answers on other dates than what has been presented here due to the missing timezone data on the shorter dates. Also my comment and disclaimer is taking care of ppl who would use my answer to sort their ambiguous dates. – mplungjan Aug 26 '23 at 19:56
-1

Just properly convert date strings to local timezone dates and sort.

(as an example I've added 2026-08-13T16:00:00-01:00 so it would go before 2026-08-13T15:00:00+02:00).

Regarding dates: since they don't contain any timezone it's assumeed they are in the local timezone:

const getDate = src => {
  
  if(src.date){

    // add time to parse in local timezone
    // if you need UTC, remove the suffix
    return new Date(src.date + 'T00:00:00');

  }
    
  const dt = new Date(src.dateTime.slice(0,19));

  // extract timezone offset from the string
  const [offH, offM] = src.dateTime.slice(19).split(':');

  // compare to the browser timezone
  const offDiff = -dt.getTimezoneOffset() - (offH * 60 + +offM);

  // correct the date to the offset difference
  dt.setMinutes(dt.getMinutes() - offDiff);

  return dt;
}

const sorted = combined.toSorted(({start: a}, {start: b}) => getDate(a) - getDate(b));

console.log(sorted);
<script>
const combined = [
{
 id: "1",
 desc: "Description One",
 start: {
         date: "2024-11-01",
        }
},
{
 id: "2",
 desc: "Description Two",
 start: {
         dateTime: "2026-08-13T17:00:00+02:00",
        }
},
{
 id: "3",
 desc: "Description Three",
 start: {
         date: "2023-03-28",
        }
},
{
 id: "4",
 desc: "Description Four",
 start: {
         dateTime: "2026-08-13T15:00:00+02:00",
        }
},
{
id: "5",
 desc: "Description Five",
 start: {
         dateTime: "2026-08-13T16:00:00-01:00",
        }
}
];
</script>
Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17