Dlaczego sekunda jest z przecinkiem?

2

https://godbolt.org/z/vv93Kcxf1

#include <fmt/core.h>
#include <fmt/chrono.h>

int main()
{
    auto now = std::chrono::system_clock::now();

    std::string filename1 = fmt::format("_memory_map1_{:%Y%m%d_%H%M%S}.txt",  fmt::localtime(std::time(nullptr)) );    
    fmt::print("{}\n",filename1);

    std::string filename2 = fmt::format("_memory_map2_{:%Y%m%d_%H%M%S}.txt",  now );    
    fmt::print("{}\n",filename2);
}

wynik:

_memory_map1_20230901_075027.txt
_memory_map2_20230901_075027.750510829.txt

Zaskoczylo mnie troche ze sekunda nie jest 0..59 ale posiada tez wartość ułamkowa i to może się czasami przydać pojawiaja mi sie jednak dodatkowe pytania:

Pytanie 1) Jak to sformatowac do n miejsc po przecinku np.
0 = 20230901_075027
1 = 20230901_075027.7
2 = 20230901_075027.75
3 = 20230901_075027.750
jeżeli zależy mi na konkretnej długości string ?

Pytanie 2) Jak ze zmiennej now usunąć/wyzerować cześć ułamkową ?

2

Ad 2.:
chrono::floor

Ad 1.:
Myślałem, że .0f pomiędzy :%Y%m%d_%H%M%S wystarczy, ale nie działa; nie widzę dlaczego, nie mam czasu myśleć, może mnie potem oświeci (a może to banalne, ale powinienem teraz co innego robić, więc…).

3

https://fmt.dev/latest/syntax.html#chrono-specs

Seconds as a decimal number. If the number of seconds is less than 10, the result is prefixed with 0. If the precision of the input cannot be exactly represented with seconds, then the format is a decimal floating-point number with a fixed format and a precision matching that of the precision of the input (or to a microseconds precision if the conversion to floating-point decimal seconds cannot be made within 18 fractional digits). The character for the decimal point is localized according to the locale. The modified command %OS produces the locale’s alternative representation.

wygląda na to, że nie ma takiego formata, który na to pozwoli. A więc musisz najpierw ręcznie zaokrąglić wartość.

2

IMO ktoś przekombinował z format string.
Nie jest to bug (bo jest udokumentowane), ale jest sprzeczne ze zdrowym rozsądkiem i najczęstszymi zastosowaniami.
Najlepiej zgłosić feature request (może ktoś to już zrobił), że ptorzebny jest symbol reprezentujacy sekundy bez częsci ułamkowej.

3

Możesz coś takiego zrobić, będzie to analogiczne do floor zaokrąglenia w matematyce, sformatować do stringa i na stringu już można normalnie formatować długość.

std::string format = fmt::format("{:%Y%m%d_%H%M%S}", now);
std::string filename2 = fmt::format("_memory_map2_{:.{}s}.txt", format, 13);
fmt::print("{}\n",filename2);

Ewentualnie jak time point cast zrobisz to możesz mieć odpowiedni czas np. w milisekundach.

using time_rate = std::chrono::seconds; // 0 miejsc po przecinku, sekunda jako dwa znaki
using time_rate = std::chrono::milliseconds; // 1/1000, czyli 3 miejsca po przecinku + . + 2 znaki sekudny
using time_rate = std::chrono::microseconds; // 1/1000_000 ...
auto now = std::chrono::time_point_cast<time_rate>(
  std::chrono::system_clock::now()
);
0

Dziękuje !
na moje skromne potrzeby wystarczył chrono::floor , na razie nie bede poprawiła fmt :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1