0

I have an array of dates:

dates: 
  [ { start: '30.05.2022 02:30:00', end: '30.05.2022 03:30:00' } 
  , { start: '30.05.2022 02:34:01', end:  '3.06.2022 04:34:01' } 
  ]

What I want is to make the start of the second item of an array to be the end of the first item of an array and without breaking duration. The desired result should look like this:

dates: 
  [ { start: '30.05.2022 02:30:00', end: '30.05.2022 03:30:00' } 
  , { start: '30.05.2022 03:30:00', end:  '3.06.2022 05:30:00' } 
  ] 

I've tried to implement my solution, but it gives incorrect result, because duration of momentjs exceeds 24 hours:

const dateFormat = 'DD.MM.YYYY HH:mm:ss'

const parseDateByMoment= (dateString) => {
  return moment(dateString, dateFormat)
}

const convertDateToString= (dateString) => {
  return dateString.format(dateFormat)

}

const addOrSubtractDate = (startDate, endDate, isAdding) => {
  const startDateDuration = moment.duration(startDate.format("HH:mm:ss"))
  const endDateDuration = moment.duration(endDate.format("HH:mm:ss"))
  
  const result = isAdding 
    ? endDateDuration + startDateDuration
    : endDateDuration - startDateDuration
  return moment.duration(result)
}

const formatToTime = (diff) => {
  return moment.utc(diff).format("HH:mm:ss.SSS");
}

const makeSequentialTimeInTracks = (dates) => {
    dates.forEach((aDate, index) => {
        if (index !== 0) {
      let prevEndDate = dates[index - 1].end
      prevEndDate = parseDateByMoment(prevEndDate)
      aDate.start = convertDateToString(prevEndDate)
      // console.log('aDate.start is', aDate.start)      
      
      const start = parseDateByMoment(aDate.start)
      const durationStart = moment.duration(start.format("HH:mm:ss"))
      console.log('2. aDate.start is', start)

      let end = parseDateByMoment(aDate.end)
      const durationEnd =  moment.duration(end.format("HH:mm:ss"))
      console.log('2. aDate.end is', end)

      let difference = addOrSubtractDate(start, end, false)
      difference = moment(difference)
      let durationDifference = moment.duration(difference.format("HH:mm:ss"))
      console.log('durationDifference', 
        moment.duration(durationDifference))

      const temp = start.clone()
      console.log('2. temp is', temp)
      temp.startOf('day').add(difference)
      console.log('temp', temp.format(dateFormat))
      // aDate.end = convertDateToString(addOrSubtractDate(start, difference, true))
        }
  });
  
  return dates
}


const sequantialTime = makeSequentialTime(dates)
console.log(dates)

Any soultion with pure JavaScript or momentjs library will be highly appreciated.

4
  • without breaking duration even if the last duration go on the next day ? Commented Jul 4, 2022 at 14:10
  • @MisterJojo yeah, you are right. Is there a simpler solution with less code? Thanks in advance Commented Jul 4, 2022 at 14:12
  • Consider using timestamps instead of full dates. Convert the start/end to timestamps, make your manipulations then back to dates. Don't work with dates in JS as they have timezones that depend on the browser/client and do not match the server. Commented Jul 4, 2022 at 16:25
  • @MisterJojo ooops. sorry, I've edited typo Commented Jul 5, 2022 at 6:06

1 Answer 1

2

"simply" do ( first version. before the OP further clarified his original question )

const makeSequentialTime = (() => // IIFE closure 
  {
  const // ---------------------------- utilities functions
    pad = n => n > 9 ? n : '0'+n // min 2 digits
  , getDateUTC = DMY_hms =>     // date string conversion to UTC (time zone = 0)
      {
      let [D,M,Y,h,m,s] = DMY_hms.split(/\.|\s|\:/).map(Number)
      return new Date(Date.UTC(Y,--M,D,h,m,s,0))
      }
  , getDate_DMY_hms = dte =>     // UTC date conversion to DMY_hms format
      ( dte.getUTCDate()          + '.'
      + pad(dte.getUTCMonth() +1) + '.'
      + dte.getUTCFullYear()      + ' '
      + pad(dte.getUTCHours())    + ':'
      + pad(dte.getUTCMinutes())  + ':'
      + pad(dte.getUTCSeconds())
    ) ;
  return (dates) =>  // main function
    {
    let
      d0_end    = getDateUTC(dates[0].end   )  
    , d1_start  = getDateUTC(dates[1].start )
    , d1_end    = getDateUTC(dates[1].end   )
    , sDelta_d1 = Math.abs(d1_start - d1_end) / 1000
      ;
    d0_end.setSeconds(d0_end.getSeconds() + sDelta_d1)

    Object.assign( dates[1], { start: dates[0].end
                             , end: getDate_DMY_hms(d0_end) })
    }
  })();


// -------------------------------------- test :

const objX = 
  { dates: 
    [ { start: '30.05.2022 02:30:00', end: '30.05.2022 03:30:00' } 
    , { start: '30.05.2022 02:34:01', end:  '3.06.2022 04:34:01' } 
  ] }

makeSequentialTime( objX.dates )

console.log ( 'result:\n' + JSON.stringify( objX.dates ).replace('},{','}\n,{') )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

PO : Could you, please, make it work for array which has many items?
It works for 2 items. Actually, I have more than 20 items in an array.

this way :

const makeSequentialTime = (() => // IIFE closure 
  {
  const // ---------------------------- utilities functions
    pad = n => n > 9 ? n : '0'+n // min 2 digits
  , getDateUTC = DMY_hms =>     // date string conversion to UTC (time zone = 0)
      {
      let [D,M,Y,h,m,s] = DMY_hms.split(/\.|\s|\:/).map(Number)
      return new Date(Date.UTC(Y,--M,D,h,m,s,0))
      }
  , getDate_DMY_hms = dte =>     // UTC date conversion to DMY_hms format
      ( dte.getUTCDate()          + '.'
      + pad(dte.getUTCMonth() +1) + '.'
      + dte.getUTCFullYear()      + ' '
      + pad(dte.getUTCHours())    + ':'
      + pad(dte.getUTCMinutes())  + ':'
      + pad(dte.getUTCSeconds())
    ) ;
  return ( dObj0, dObj1 ) =>  // main function ( separate d0 and d1 )
    {
    let
      d0_end    = getDateUTC(dObj0.end   )  
    , d1_start  = getDateUTC(dObj1.start )
    , d1_end    = getDateUTC(dObj1.end   )
    , sDelta_d1 = Math.abs(d1_start - d1_end) / 1000
      ;
    d0_end.setSeconds(d0_end.getSeconds() + sDelta_d1)

    Object.assign( dObj1, { start: dObj0.end
                          , end: getDate_DMY_hms(d0_end) })
    return  dObj1  // addition for reduce method                 
    }
  })();
  


// -------------------------------------- test :
  

const objY = 
  { dates: 
    [ { start: '11.05.2022 02:30:00', end: '11.05.2022 03:30:00' } 
    , { start: '11.05.2022 02:34:01', end:  '3.06.2022 04:34:01' } 
    , { start: '14.05.2022 02:30:00', end: '14.05.2022 03:30:00' } 
    , { start: '14.05.2022 02:34:01', end:  '3.06.2022 04:34:01' } 
    , { start: '30.05.2022 02:30:00', end: '30.05.2022 03:30:00' } 
    , { start: '30.05.2022 02:34:01', end:  '3.06.2022 04:34:01' }
  // ...
  ] } 

objY.dates.reduce( makeSequentialTime )
// same as :
// objY.dates.reduce( (prev, curr) => makeSequentialTime( prev, curr ) )

// show result :
console.log ( 'result:\n' + JSON.stringify( objY.dates ).replaceAll('},{','}\n,{') )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for your response! I really appreciate your answer! Could you, please, make it work for array which has many items? It works for 2 items. Actually, I have more than 20 items in an array.

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.