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

2

7

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?

Glary answered 6/4, 2021 at 20:53 Comment(0)
S
8

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,
});
Selfpity answered 6/4, 2021 at 21:49 Comment(2)
It's hour and minute instead of hours and minutes in the above .set example REF moment.github.io/luxon/docs/class/src/…Mensal
Thanks for the pickup @Mensal - I've fixed it up.Selfpity
B
2

I had the same issue. I am currently working with Strapi and used its Datepicker component. This component returns JSDate.

enter image description here

 const ourTime = "17:34"
 // Parse time to object
 const { minute, hour } = DateTime.fromFormat(ourTime, 'hh:mm').toObject()

 const dt = DateTime.fromJSDate(dateFromComponent, { zone: 'gmt' })
 const inLocal = dt.toLocal().setZone('yourZone')
 console.log(inLocal, 'Our current date')

What we have for now in console.log: enter image description here

 const addedHoursAndMinutes = inLocal.set({ hour: hour, minute: minute })
 console.log(
     inLocal.set({ hour: hour, minute: minute }),  // Here is magic happens
     'Our current date with overwritten hours and mins'
 )

And we get what we need: enter image description here


Answer in short:

You can use .set({ hour: 17, minute: 34 }) on luxon's DateTime object.

P.S. Works not only for hours and minutes. .set({years: 2001,months: 5,days: 5,hours: 0,minutes: 0,seconds: 0,milliseconds: 0}) Pay no attention to [s] at the end of the words (hour/hours, day/days, etc - both variants are working)

Bilander answered 26/10, 2022 at 11:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.