javascriptreactjstypescriptluxon

Can I use Luxon to combine a DateTime with a time string?


I've got a TimePicker component that returns a 24-hour time in this format: 09:00 for 9AM or 12:00 for 12PM or 20:00 for 8PM. Something in my code requires a Date (JSDate) so I want to just take the current date/time DateTime.now() but apply the hours and minutes from the TimePicker component which has an onClick event. I can handle that event like so:

// TimePickerValue can either be a string or JSDate
// but the TimePicker is always returning a string
const handleTimeChange = (time:TimePickerValue) => {
  // this outputs a time in 24-hour format
  console.log("handleTimeChange: ", time) 
    
  // I want to set the state of the parent component
  // this needs to be in JSDate format so this doesn't work
  // setSomeValue(time)

  // Because I don't care about date, I can just use "now()" and convert
  // it to a JSDate but I want the hours and minutes of the value I'm setting
  // to be the time in the string being sent to this function.
  setSomeValue(DateTime.now().toJSDate())
}

Can Luxon parse something like "13:00" or apply it an existing DateTime so it writes over its existing hours and minutes?


Solution

  • Can Luxon parse something like "13:00"

    Yes, you can just use the fromISO method to parse a time string.

    const parsed = DateTime.fromISO('20:00');
    console.log(parsed.toString());  // 2021-04-07T20:00:00.000+10:00
    

    Can Luxon apply it to an existing DateTime so it writes over its existing hours and minutes?

    This could be a bit harder, I don't know if there's a "built-in" way in Luxon to do that. But, if you parse the time string using fromISO, it will set the date part to "today", so you could use diff to work out the "time of day" (as a Duration) and then use that to set the time of day on your other date:

    const parsed = DateTime.fromISO(time);
    const today = DateTime.now().startOf('day');
    const timeOfDay = parsed.diff(today);
    
    const dateToModify = DateTime.fromJSDate(otherDate);
    const result = dateToModify.startOf('day').plus(timeOfDay);
    

    Alternatively, if you have the "parts" of the time, you can use Luxon's set method to overwrite those individual parts:

    const dateToModify = DateTime.fromJSDate(otherDate);
    
    // Not sure what's in the 'TimePickerValue' object but if you had hours and minutes:
    const result = dateToModify.set({
        hour: time.hours,
        minute: time.minutes,
    });