logo

utils

Old programs, got split in utils-std and utils-extra git clone https://hacktivis.me/git/utils.git

iso_parse.c (1688B)


  1. // Collection of Unix tools, comparable to coreutils
  2. // SPDX-FileCopyrightText: 2023 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _DEFAULT_SOURCE // tm_gmtoff/tm_zone
  5. #define _XOPEN_SOURCE 700 // strptime (NetBSD)
  6. #define _POSIX_C_SOURCE 200809L // st_atim/st_mtim
  7. #include <ctype.h> /* isdigit */
  8. #include <errno.h> /* errno */
  9. #include <stdio.h> /* perror, sscanf */
  10. #include <stdlib.h> /* exit */
  11. #include <string.h> /* memset */
  12. #include <time.h> /* strptime, tm */
  13. // Calls exit() on failure
  14. struct timespec
  15. iso_parse(char *arg)
  16. {
  17. // YYYY-MM-DD[T ]hh:mm:SS([,\.]frac)?Z?
  18. // Dammit Unixes why no nanoseconds in `struct tm` nor `strptime`
  19. struct timespec time = {.tv_sec = 0, .tv_nsec = 0};
  20. // For Alpine's abuild compatibility
  21. if(arg[0] == '@')
  22. {
  23. arg++;
  24. errno = 0;
  25. time.tv_sec = strtol(arg, NULL, 10);
  26. if(errno != 0)
  27. {
  28. perror("strtol");
  29. exit(EXIT_FAILURE);
  30. }
  31. return time;
  32. }
  33. struct tm tm;
  34. memset(&tm, 0, sizeof(tm));
  35. // No %F in POSIX
  36. char *s = strptime(arg, "%Y-%m-%d", &tm);
  37. if(s[0] != 'T' && s[0] != ' ') exit(EXIT_FAILURE);
  38. s++;
  39. s = strptime(s, "%H:%M:%S", &tm);
  40. if(s[0] == ',' || s[0] == '.')
  41. {
  42. double fraction = 0.0;
  43. int parsed = 0;
  44. if(s[0] == ',') s[0] = '.';
  45. if(sscanf(s, "%10lf%n", &fraction, &parsed) < 1) exit(EXIT_FAILURE);
  46. time.tv_nsec = fraction * 1000000000;
  47. s += parsed;
  48. // too many digits
  49. if(isdigit(s[0])) exit(EXIT_FAILURE);
  50. }
  51. if(s[0] == 'Z')
  52. {
  53. tm.tm_gmtoff = 0;
  54. tm.tm_zone = "UTC";
  55. }
  56. time.tv_sec = mktime(&tm);
  57. if(time.tv_sec == (time_t)-1)
  58. {
  59. perror("mktime");
  60. exit(EXIT_FAILURE);
  61. }
  62. return time;
  63. }