epezent / epezent/implot

How to independently use `ShowDatePicker` and `ShowTimePicker` to select date/time? [Almost solved]

Open
#521 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
6.2k
Forks
693
PR merge metrics
No merged PRs in 30d

Description

@epezent is it necessary to wrap `ShowDatePicker` and `ShowTimePicker` to a single and independent function/widget to use? I think they are really good to use and beautiful, and did some work to wrap them together. I tried to initialize and use `ShowDatePicker` and `ShowTimePicker` but faced with some problems so I raised this issue. After coding for a while I managed to solve most of them.

Basically, I want to pick a date and a time using the popup widget, save them to a std::string like `2023-05-06 15:24:16`, and show them by `ImGui::Text()`. Also I will save the string to a json file. Next time when I open the program, I will load the date and time from json, parse the string and show them. Also I can initialize the widget again by the loaded date and time, and change them again by the widget.

The desired function/widget may support the following features:

1) [**Solved**] Switch from 12-hour system to 24-hour system. Solved by setting
```cpp
ImPlotStyle &style = ImPlot::GetStyle();
style.Use24HourClock = true;
```

2) [**Partially solved**] Initialize the widget by inputting a UTC string and a TimeZone string under different hour system. Currently 24-hour system. **HAVEN'T TRIED** to initialize under 12-hour system.

3) [**Solved**] Support microseconds.
---

I placed the code below in case someone may need.

```cpp
inline time_t timegm(std::tm *tm) // calculate seconds without timezone
{
#ifdef _WIN32
return _mkgmtime(tm);
#else
return timegm(tm);
#endif
}

//...in render loop
if (ImGui::Button("Change"))
ImGui::OpenPopup("SelectDateTime##");
static std::string strDateTime = "2020-01-01 10:11:23";
static std::string strTimeZone = "UTC-3";
ImPlot_DateTimePicker(strDateTime, strTimeZone);
//...

std::string timestamp2string(std::time_t timestamp)
{
std::tm *tm = std::gmtime(×tamp);
char buffer[80];
std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm);
return buffer;
}

int timezone2int(const std::string tzstring)
{
size_t found = tzstring.find("UTC");
if (found != std::string::npos)
{
std::string number_str = tzstring.substr(found + 3);
std::stringstream ss(number_str);
int number;
ss >> number;
return number;
}
else
return 0;
}

std::string ImPlot_DateTimePicker(std::string &UTCdatetime, std::string TimeZone = "UTC+0")
{
std::tm tm = {};
std::stringstream ss(UTCdatetime);
ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S.%f");
static std::time_t timestamp0 = timegm(&tm) + timezone2int(TimeZone) * 3600; // current timestamp of current timezone
std::tm tm_midnight = tm;
tm_midnight.tm_hour = tm_midnight.tm_min = tm_midnight.tm_sec = 0;
static std::time_t timestamp_midnight = timegm(&tm_midnight);
static std::time_t deltaDate = timestamp0 - timestamp_midnight;
if (ImGui::BeginPopup("SelectDateTime##"))
{
static int PickerLevel = 0;
static ImPlotTime time_selected = timestamp0;
static ImPlotTime date_selected = timestamp0;
ImPlotStyle &style = ImPlot::GetStyle();
style.Use24HourClock = true;
// `TimePicker` only changes hour, minute, second around initial timestamp `time_stamp0`
ImPlot::ShowTimePicker("##time", &time_selected);
std::time_t deltaTime = time_selected.S - timestamp0; // delta second of `current timestamp selection - initial timestamp` by Time Picker
// set milliseconds besides `TimePicker`
static int ms = 0;
std::size_t dotPos = UTCdatetime.find_first_of('.');
if (dotPos != std::string::npos)
ms = stoi(UTCdatetime.substr(dotPos + 1));
ImGui::SameLine();
ImGui::Text(".");
ImGui::SameLine();
ImGui::PushItemWidth(5 * ImGui::GetFontSize());
ImGui::InputInt("##milliseconds", &ms);
ImGui::PopItemWidth();
ms = CLAMP(ms, 0, 999);
std::stringstream ss;
ss << std::setw(3) << std::setfill('0') << ms;
ImGui::Separator();
// `DatePicker` directly select and return timestamp at midnight (i.e., timestamp of different date at 00:00:00)
ImPlot::ShowDatePicker("##date", &PickerLevel, &date_selected, &date_selected);
std::time_t timestamp = date_selected.S + deltaDate + deltaTime; // current timestamp
UTCdatetime = timestamp2string(timestamp) + "." + ss.str();
ImGui::EndPopup();
}

}
```

---

Screenshot. The time zone selection combobox is not included in the code

Image

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.