timezone.scm 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (gnu installer timezone)
  19. #:use-module (gnu installer utils)
  20. #:use-module (guix i18n)
  21. #:use-module (srfi srfi-1)
  22. #:use-module (srfi srfi-26)
  23. #:use-module (srfi srfi-34)
  24. #:use-module (srfi srfi-35)
  25. #:use-module (ice-9 match)
  26. #:use-module (ice-9 receive)
  27. #:export (locate-children
  28. timezone->posix-tz
  29. timezone-has-child?
  30. zonetab->timezone-tree
  31. posix-tz->configuration))
  32. (define %not-blank
  33. (char-set-complement char-set:blank))
  34. (define (posix-tz->timezone tz)
  35. "Convert given TZ in Posix format like \"Europe/Paris\" into a list like
  36. (\"Europe\" \"Paris\")."
  37. (string-split tz #\/))
  38. (define (timezone->posix-tz timezone)
  39. "Convert given TIMEZONE like (\"Europe\" \"Paris\") into a Posix timezone
  40. like \"Europe/Paris\"."
  41. (string-join timezone "/"))
  42. (define (zonetab->timezones zonetab)
  43. "Parse ZONETAB file and return the corresponding list of timezones."
  44. (define (zonetab-line->posix-tz line)
  45. (let ((tokens (string-tokenize line %not-blank)))
  46. (match tokens
  47. ((code coordinates tz _ ...)
  48. tz))))
  49. (call-with-input-file zonetab
  50. (lambda (port)
  51. (let* ((lines (read-lines port))
  52. ;; Filter comment lines starting with '#' character.
  53. (tz-lines (filter (lambda (line)
  54. (not (eq? (string-ref line 0)
  55. #\#)))
  56. lines)))
  57. (map (lambda (line)
  58. (posix-tz->timezone
  59. (zonetab-line->posix-tz line)))
  60. tz-lines)))))
  61. (define (timezones->timezone-tree timezones)
  62. "Convert the list of timezones, TIMEZONES into a tree under the form:
  63. (\"America\" (\"North_Dakota\" \"New_Salem\" \"Center\"))
  64. representing America/North_Dakota/New_Salem and America/North_Dakota/Center
  65. timezones."
  66. (define (remove-first lists)
  67. "Remove the first element of every sublists in the argument LISTS."
  68. (map (lambda (list)
  69. (if (null? list) list (cdr list)))
  70. lists))
  71. (let loop ((cur-timezones timezones))
  72. (match cur-timezones
  73. (() '())
  74. (((region . rest-region) . rest-timezones)
  75. (if (null? rest-region)
  76. (cons (list region) (loop rest-timezones))
  77. (receive (same-region other-region)
  78. (partition (lambda (timezone)
  79. (string=? (car timezone) region))
  80. cur-timezones)
  81. (acons region
  82. (loop (remove-first same-region))
  83. (loop other-region))))))))
  84. (define (locate-children tree path)
  85. "Return the children of the timezone indicated by PATH in the given
  86. TREE. Raise a condition if the PATH could not be found."
  87. (let ((extract-proc (cut map car <>)))
  88. (match path
  89. (() (sort (extract-proc tree) string<?))
  90. ((region . rest)
  91. (or (and=> (assoc-ref tree region)
  92. (cut locate-children <> rest))
  93. (raise
  94. (condition
  95. (&message
  96. (message
  97. (format #f (G_ "Unable to locate path: ~a.") path))))))))))
  98. (define (timezone-has-child? tree timezone)
  99. "Return #t if the given TIMEZONE any child in TREE and #f otherwise."
  100. (not (null? (locate-children tree timezone))))
  101. (define* (zonetab->timezone-tree zonetab)
  102. "Return the timezone tree corresponding to the given ZONETAB file."
  103. (timezones->timezone-tree (zonetab->timezones zonetab)))
  104. ;;;
  105. ;;; Configuration formatter.
  106. ;;;
  107. (define (posix-tz->configuration timezone)
  108. "Return the configuration field for TIMEZONE."
  109. `((timezone ,timezone)))