1 ;;; GNU Guix --- Functional package management for GNU
2 ;;; Copyright © 2018 Mathieu Othacehe <m.othacehe@gmail.com>
4 ;;; This file is part of GNU Guix.
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.
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.
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/>.
19 (define-module (gnu installer timezone)
20 #:use-module (gnu installer utils)
21 #:use-module (guix i18n)
22 #:use-module (srfi srfi-1)
23 #:use-module (srfi srfi-26)
24 #:use-module (srfi srfi-34)
25 #:use-module (srfi srfi-35)
26 #:use-module (ice-9 match)
27 #:use-module (ice-9 receive)
28 #:export (locate-children
31 zonetab->timezone-tree
32 posix-tz->configuration))
35 (char-set-complement char-set:blank))
37 (define (posix-tz->timezone tz)
38 "Convert given TZ in Posix format like \"Europe/Paris\" into a list like
39 (\"Europe\" \"Paris\")."
40 (string-split tz #\/))
42 (define (timezone->posix-tz timezone)
43 "Convert given TIMEZONE like (\"Europe\" \"Paris\") into a Posix timezone
44 like \"Europe/Paris\"."
45 (string-join timezone "/"))
47 (define (zonetab->timezones zonetab)
48 "Parse ZONETAB file and return the corresponding list of timezones."
50 (define (zonetab-line->posix-tz line)
51 (let ((tokens (string-tokenize line %not-blank)))
53 ((code coordinates tz _ ...)
56 (call-with-input-file zonetab
58 (let* ((lines (read-lines port))
59 ;; Filter comment lines starting with '#' character.
60 (tz-lines (filter (lambda (line)
61 (not (eq? (string-ref line 0)
66 (zonetab-line->posix-tz line)))
69 (define (timezones->timezone-tree timezones)
70 "Convert the list of timezones, TIMEZONES into a tree under the form:
72 (\"America\" (\"North_Dakota\" \"New_Salem\" \"Center\"))
74 representing America/North_Dakota/New_Salem and America/North_Dakota/Center
77 (define (remove-first lists)
78 "Remove the first element of every sublists in the argument LISTS."
80 (if (null? list) list (cdr list)))
83 (let loop ((cur-timezones timezones))
86 (((region . rest-region) . rest-timezones)
87 (if (null? rest-region)
88 (cons (list region) (loop rest-timezones))
89 (receive (same-region other-region)
90 (partition (lambda (timezone)
91 (string=? (car timezone) region))
94 (loop (remove-first same-region))
95 (loop other-region))))))))
97 (define (locate-children tree path)
98 "Return the children of the timezone indicated by PATH in the given
99 TREE. Raise a condition if the PATH could not be found."
100 (let ((extract-proc (cut map car <>)))
102 (() (sort (extract-proc tree) string<?))
104 (or (and=> (assoc-ref tree region)
105 (cut locate-children <> rest))
110 (format #f (G_ "Unable to locate path: ~a.") path))))))))))
112 (define (timezone-has-child? tree timezone)
113 "Return #t if the given TIMEZONE any child in TREE and #f otherwise."
114 (not (null? (locate-children tree timezone))))
116 (define* (zonetab->timezone-tree zonetab)
117 "Return the timezone tree corresponding to the given ZONETAB file."
118 (timezones->timezone-tree (zonetab->timezones zonetab)))
122 ;;; Configuration formatter.
125 (define (posix-tz->configuration timezone)
126 "Return the configuration field for TIMEZONE."
127 `((timezone ,timezone)))