epezent / implot

Immediate Mode Plotting
MIT License
4.48k stars 491 forks source link

ShowDatePicker Misses dates when UseLocalTime = true #256

Open peterwilson136 opened 3 years ago

peterwilson136 commented 3 years ago

Using the code below, if you click on June 2021 -> Jan ->1 (and make sure you click on the 1), and then you go back to January 2021 -> Jun, it puts the date to 31 May, 2021. You can repeat this for May, June, July, August, September, October, and you will see that it only works up till April and after November.

#include <GL/glew.h>

#ifndef GLFW_INCLUDE_NONE
#define GLFW_INCLUDE_NONE // GLFW including OpenGL headers causes ambiguity or multiple definition errors.
#endif // GLFW_INCLUDE_NONE

#include <GLFW/glfw3.h>

#include "ImGui/imgui.h"
#include "ImGui/implot.h"
#include "ImGui/implot_internal.h"
#include "ImGui/imgui_impl_glfw.h"
#include "ImGui/imgui_impl_opengl3.h"

int main(int argc, char* argv[])
{
    glfwInit();
    GLFWwindow* window = glfwCreateWindow(1280, 720, "Program", NULL, NULL);
    glfwMakeContextCurrent(window);
    glfwSwapInterval(0); //  vsync

    glewInit();

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImPlot::CreateContext();

    ImGui::StyleColorsDark();
    ImPlotStyle& ImPlot_Style = ImPlot::GetStyle();
    ImPlot_Style.UseLocalTime = true;

    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init("#version 460");

    static ImPlotTime from = 1623938400 - 86400;
    static int fromLevel = 0;

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        ImGui::Text("%.3f", ImGui::GetIO().Framerate);
        ImPlot::ShowDatePicker("##ComparisonBefore", &fromLevel, &from, nullptr, &from);

        ImGui::Render();
        glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        glfwSwapBuffers(window);
    }

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImPlot::DestroyContext();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}

Edit: I think it has to do with ImPlot_Style.UseLocalTime = true;, because removing this solves the issue, however in my main program it messes with the time in the plot axis.

epezent commented 3 years ago

It does in fact look like we have a bug when UseLocalTime is enabled. It's not immediately clear to me why.

However, because this is 1) still somewhat functional, 2) just convenience feature for time series axes context menus, and 3) an internal API function (use at your own risk!), I'm going to hold off on fixing until more impactful work is complete.

In the meantime, please consider investigating the issue and submitting a PR to fix it. I will happily review it.

peterwilson136 commented 3 years ago

@epezent I think I found the same issue rooted elsewhere and may help. I am just documenting it on this thread. Using this code,

ImGui::SetNextWindowSize({ 1173,370 });
ImGui::SetNextWindowPos({ 50,100 });
ImGui::Begin("window");
if (ImPlot::BeginPlot("Plot", nullptr, nullptr, {-1, 0}, 0, ImPlotAxisFlags_Time)) {
    static double xs[] = { 1610000000, 1620000000, 1630000000, 1640000000, 1650000000 };
    static double ys[5] = { 5, 10, 15, 20, 25 };
    ImPlot::PlotLine("Test", xs, ys, 5);
    ImPlot::EndPlot();
}
ImGui::End();

the times at the bottom begin as the names of the months. Where there's grid lines up from each month, zoom into October slowly, as the names transition to the Month/Day format, October becomes 11/1, which is actually November. What's weird is as you test this for months before it, it works fine, but for some reason on October specifically (in an area around it, and the only one I could find so far), it doesn't work. I should also mention that from the get-go, you can see the axis plot has two April's next to each other at the beginning.

shrddr commented 1 month ago

In my locale, 31 Mar 2024 the Daylight Saving Time has started (at 03:00:00 local = 01:00:00 GMT clocks were turned forward 1 hour to 04:00:00 local = 01:00:00 GMT) and since then time axis ticks started behaving differently. Here's a test case to confirm:


ImPlot::GetStyle().UseLocalTime = true;
ImGui::Checkbox("Local Time", &ImPlot::GetStyle().UseLocalTime);

static double t_min = 1711846799; // Mar 31 2024 00:59:59 GMT+0

ImGui::Text("t_min = not yet DST = OK");
if (ImPlot::BeginPlot("##ok", ImVec2(600, 200))) {
    ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
    ImPlot::SetupAxesLimits(t_min, t_min + 360 * 86400, 0, 1);
    ImPlot::EndPlot();
}

t_min += 1; // Mar 31 2024 01:00:00 GMT+0

ImGui::Text("t_min = is DST = bug");
if (ImPlot::BeginPlot("##bug", ImVec2(600, 200))) {
    ImPlot::SetupAxisScale(ImAxis_X1, ImPlotScale_Time);
    ImPlot::SetupAxesLimits(t_min, t_min + 360 * 86400, 0, 1);
    ImPlot::EndPlot();
}
ImGui::End();

image

You can observe it by dragging time axis left and right on either plot, the January 1 label keeps changing between --01 and --12 when t_min crosses the DST point.

The cause is:

So I think an easy fix would be to always clear gp.Tm.tm_isdst in FloorTime but not sure how it affects other functionality.

shrddr commented 1 month ago

So I think an easy fix would be to always clear gp.Tm.tm_isdst in FloorTime

Uhh it's complex, FloorTime should behave differently depending on unit argument

shrddr commented 1 month ago

gp.Tm.tm_isdst = -1; this forces MakeTime to infer if it is DST or not from other fields