date_format.cxx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. //
  2. // date_format.cxx
  3. // logging
  4. //
  5. // Created by Sam Jaffe on 4/4/19.
  6. //
  7. #include <ctime>
  8. #include <functional>
  9. #include <string>
  10. #include "logger/exception.h"
  11. #include "logger/format.h"
  12. #include "logger/logger_fwd.h"
  13. #include "logger/logpacket.h"
  14. namespace logging {
  15. std::string fmt_time(struct timeval round, char const * const fmt) {
  16. struct tm time;
  17. // Supports localtime when requested, but you can't really test that
  18. if (strstr(fmt, "%z") || strstr(fmt, "%Z")) {
  19. localtime_r(&round.tv_sec, &time);
  20. } else {
  21. gmtime_r(&round.tv_sec, &time);
  22. }
  23. char buf[64] = {'\0'};
  24. std::strftime(buf, sizeof(buf), fmt, &time);
  25. return buf;
  26. }
  27. std::string fmt_time_with_milis(struct timeval round,
  28. std::string const & fmt) {
  29. char buf[64] = {'\0'};
  30. snprintf(buf, sizeof(buf), fmt.c_str(), round.tv_usec/1000);
  31. return fmt_time(round, buf);
  32. }
  33. string_generator get_date_formatter(std::string fmt) {
  34. if (fmt.find("%_ms") != std::string::npos) {
  35. size_t pos = 0;
  36. while ((pos = fmt.find("%", pos)) != std::string::npos) {
  37. fmt.replace(pos, 1, "%%");
  38. pos += 2;
  39. }
  40. fmt.replace(fmt.find("%%_ms"), 5, "%.03d");
  41. return [=](logpacket const & lp) {
  42. return fmt_time_with_milis(lp.time, fmt);
  43. };
  44. } else {
  45. return [=](logpacket const & lp) {
  46. return fmt_time(lp.time, fmt.c_str());
  47. };
  48. }
  49. }
  50. string_generator parse_date_format_string(char const * str) {
  51. char const * const end = strchr(str, '}');
  52. if (end == nullptr) {
  53. std::string error_msg{"expected date-format specifier to terminate"};
  54. throw format_parsing_exception{error_msg};
  55. }
  56. return get_date_formatter(std::string(str, end));
  57. }
  58. }