Search code examples
reactjsflatpickr

Get Flatpickr time data in Unix format


I am using Flatpickr for a few date and time requirements in a React-driven project. Specifically i am using the React flavoured library React-flatpickr.

It works fine and there are no issues when i use it for either the date or time fields providing standalone data.

My requirement has a date picker where the user chooses a date using the default calendar view.

Two additional related fields allow the user to choose a start time and an end time. These 2 fields only show the time choice - there is no calendar view.

In the options, besides other data, the dateFormat is passed K since i want the Unix epoch time for my processing while the view returned to the user may have friendlier formats. This works fine for the date field. The time fields should return back Unix epoch based time for the day chosen in the date field. I get back a single digit (Eg. 6) when i pass K for the time fields. If my understanding is right the time fields gets the date from the defaultDate or value options.

A sample layout is attached for some visual reference:

A rough layout of the date and 2 time fields

How do i get the Unix time for these time fields based on the date chosen in the date field? For example i am looking for these values:

  • start date: 123456789009 (sample time from the 'startdate' field, ideally the 00:00:00 AM time in Unix epoch format)
  • startime: 98765432236 (sample time from the 'starttime' field, the date being based on the 'startdate' field with the time chosen in this field. Will default to the Unix epoch time for 06:00:00 AM if null)
  • endtime: 934236111833 (sample time from the 'endtime' field, the date being based on the 'startdate' field with the time chosen in this field. Will default to the Unix epoch time for 11:59:59 PM if null )

My work-in-progress/rough React code: (Note: some elements and classes etc that was used for layout and styling have been removed for brevity to ensure enhanced readability. I am using Redux so may not be using the local state at all. The local state is just so that i could get a working version going. )

class SelectDateTime extends React.Component{
   state={
      startdate: new Date().getTime(),
      starttime: "",
      endtime: "",
   }
   startDateChanged=(date)=>{
    this.setState({
        ...this.state,
        startdate: date
    })
   }
   startTimeChanged=(time)=>{
    this.setState({
        ...this.state,
        starttime: time
    })
  }
  endTimeChanged=(time)=>{
    this.setState({
        ...this.state,
        endtime: time
    })
  }
  render(){
    const { startdate, starttime, endtime } = this.state;
    return(
        <React.Fragment>
          <div>
             Start Date
             <Flatpickr                 
                 value={startdate}
                 options={{
                        wrap: true,
                        minDate: 'today',
                        altInput: true, 
                        altFormat: "F j, Y",
                        dateFormat: "U"
                    }}
                    onChange={date => { this.startDateChanged(date) }} 
                >
                <input type='text' data-input />
                <button type='button' data-toggle>Select</button>
            </Flatpickr>
          <div>
            Start Time
            <Flatpickr                 
                value={starttime}
                options={{
                    wrap: true,
                    enableTime: true,
                    noCalendar: true,
                    //dateFormat: "H:i",
                    altInput: true,
                    altFormat: "H:i K",
                    dateFormat: "U",
                    defaultDate: startdate,
                    minDate: "06:00",
                    maxDate: "23:59"
                }}
                    onChange={time => { this.startTimeChanged(time) }} 
                >
                <input type='text' data-input />
                <button type='button' data-toggle>Select</button>
            </Flatpickr>
          </div>
          <div>
             End Time
            <Flatpickr                 
                value={startdate}
                //value={endtime}
                options={{
                    wrap: true,
                    enableTime: true,
                    noCalendar: true,
                    altInput: true,
                    altFormat: "H:i K",
                    dateFormat: "U",
                    defaultDate: "startdate",
                    minDate: "06:00",
                    maxDate: "23:59"
                }}
                onChange={time => { this.endTimeChanged(time) }} 
                >
                <input type='text' data-input />
                <button type='button' data-toggle>Select</button>
             </Flatpickr>
          </div>
        </React.Fragment>
    )
}

}


Solution

  • I think i may have posted the question without really attempting a few more probable solutions - i had just got acquainted with the library and posed the question within the hour as i knew there wouldn't be too many online resources as yet (i did try a few options but thought that perhaps my approach lacked a fundamental required modification that was not documented).

    A few changes to my code and i was able to solve my primary issue.

    state={
        startdate: Math.round((new Date()).setUTCHours(0,0,0,0)),
        starttime: null,
        endtime: null,
    }
    
    
      <Flatpickr                 
        value={startdate}
        options={{
         wrap: true,
         minDate: 'today',
         altInput: true, 
         altFormat: "F j, Y",
         dateFormat: "U"
       }}
      onChange={date => { this.startDateChanged(date) }} 
      >
      /* ...other code here  */
     </Flatpickr>
    
    
     <Flatpickr
       key={startdate}
       options={{
        wrap: true,
        enableTime: true,
        noCalendar: true,
        altInput: true,
        altFormat: "H:i K",
        dateFormat: "U",
        defaultDate: startdate,
       }}
       onChange={time => { this.startTimeChanged(time) }} 
      >
      /* ...other code here  */
      </Flatpickr>
    
      <Flatpickr
       key={startdate}
       options={{
        wrap: true,
        enableTime: true,
        noCalendar: true,
        altInput: true,
        altFormat: "H:i K",
        dateFormat: "U",
        defaultDate: startdate,
       }}
       onChange={time => { this.endTimeChanged(time) }} 
      >
      /* ...other code here  */
      </Flatpickr>
    

    Main changes include:

    • Adding a key attribute enabled the time fields to pick up changes in the state
    • Removed value attribute as well as removed(perhaps temporarily) the minTime and maxTime properties
    • enforcing a midnight time in the state for the startdate

    There are a few issues which i am ironing out but at least i got my primary problems solved.

    For this project, i am proactively trying to trim down file size as much as possible so my first automatic choice of a Moment(library) driven solution was out. I did think of Luxon and Date-fns but FlatPickr caught my eye since it has no dependencies and has a picker already baked in(in fact it is a picker-focussed date/time solution) and if the need ever arose has locale support as well. Having a pre-built React-ready component helped in the decision making as well.