Hacker0x01 / react-datepicker

A simple and reusable datepicker component for React
https://reactdatepicker.com/
MIT License
8.12k stars 2.24k forks source link

UTC With Offset #5190

Open coopernicholas opened 4 weeks ago

coopernicholas commented 4 weeks ago

I am trying to get a date range into a filter. It works but start always adds 5 hours to the actual time. Any help or recommendations?


 const [startDate, setStartDate] = useState(
    DateTime.now().minus({ days: 1 }).setZone("utc").toJSDate()
  );

  const [endDate, setEndDate] = useState(DateTime.utc().toJSDate());

  const handleStartDateChange = (date) => {
    if (date) {
      // Convert to UTC before setting state
      setStartDate(DateTime.fromJSDate(date).setZone("utc").toJSDate());
    }
  };

  const handleEndDateChange = (date) => {
    if (date) {
      // Convert to UTC before setting state
      setEndDate(DateTime.fromJSDate(date).setZone("utc").toJSDate());
    }
  };

  useEffect(() => {
    const filteredData = sensorData.filter((item) => {
      const itemDate = DateTime.fromISO(item.dateTime, { zone: "utc" });

      const start = DateTime.fromJSDate(startDate).setZone("utc");
      const end = DateTime.fromJSDate(endDate).setZone("utc");

      return item.sensorId === sensorId && itemDate >= start && itemDate <= end;
    });

    // Prepare data for the chart
    const tempData = [];
    const humData = [];
    const dateTimeLabels = [];

    filteredData.forEach((item) => {
      dateTimeLabels.push(
        DateTime.fromISO(item.dateTime, { zone: "utc" }).toFormat(
          "MMM dd hh:mm a"
        )
      );
      tempData.push(item.temperature !== null ? item.temperature : 0); // Use 0 if temperature is null
      humData.push(item.humidity !== null ? item.humidity : 0); // Use 0 if humidity is null
    });

    setLabels(dateTimeLabels);
    setTemperature(tempData);
    setHumidity(humData);
  }, [sensorData, sensorId, startDate, endDate]);

  const data = {
    labels: labelData,
    datasets: [
      {
        label: "Temperature",
        backgroundColor: "rgba(220, 220, 220, 1)",
        data: temperature,
        unitSuffix: "°F",
      },
      {
        label: "Humidity",
        backgroundColor: "rgba(151, 187, 205, 1)",
        data: humidity,
        unitSuffix: "%",
      },
    ],
  };

  const options = {
    scales: {
      x: {
        beginAtZero: true,

        // type: "time",
        // bounds: "ticks",

        // time: {
        //   round: "hour",
        //   tooltipFormat: "Pp",
        //   displayFormats: {
        //     minute: "MMM d, h:mm a",
        //     hour: "MMM d, h a",
        //   },
        // },
        title: {
          display: true,
          text: "Date",
        },
      },
      y: {
        beginAtZero: true,
        title: {
          display: true,
          text: "Values",
        },
      },
    },
    plugins: {
      tooltip: {
        callbacks: {
          label: (item) =>
            `${item.dataset.label}: ${item.formattedValue}${item.dataset.unitSuffix}`,
        },
      },
    },
  };

  if (loading) return <div>Loading...</div>;
  if (error) return <div>{error}</div>;

  return (
    <CRow>
      <CCol xs>
        <CCard className="mb-4">
          <CCardHeader>
            Select Date:
            <div>
              <label>Start Date:</label>
              <DatePicker
                selected={DateTime.fromJSDate(startDate).toLocal().toJSDate()}
                onChange={handleStartDateChange}
                showTimeSelect
                timeIntervals={60}
                timeFormat="HH:mm"
                dateFormat="MMMM d, yyyy h:mm aa"
                timeCaption="Time"
              />
            </div>
            <div>
              <label>End Date:</label>
              <DatePicker
                selected={DateTime.fromJSDate(endDate).toLocal().toJSDate()} // Display in local time
                onChange={handleEndDateChange}
                showTimeSelect
                timeIntervals={60}
                timeFormat="HH:mm"
                dateFormat="MMMM d, yyyy h:mm aa"
                timeCaption="Time"
              />
            </div>
          </CCardHeader>
          <CCardBody>
            <Bar data={data} options={options} />
          </CCardBody>
        </CCard>
      </CCol>
    </CRow>
  );
};

export default ChildComponent;
coopernicholas commented 4 weeks ago

I was able to get it to work by changing the following:

 const filteredData = sensorData.filter((item) => {
      const itemDate = DateTime.fromISO(item.dateTime, { zone: "utc" });

      const start = DateTime.fromJSDate(startDate).setZone("America/Chicago");
      const end = DateTime.fromJSDate(endDate).setZone("America/Chicago");

      return (
        item.sensorId === sensorId &&
        itemDate.toString() >= start.toString() &&
        itemDate.toString() <= end.toString()
      );
    });

I know comparing the strings may be incorrect but it is the only option.