branch: elpa/datetime
commit 4d11de332682e9942ad00c0ac86d79c8e1789329
Author: Paul Pogonyshev <pogonys...@gmail.com>
Commit: Paul Pogonyshev <pogonys...@gmail.com>

    Upgrade to fetching data from Java 17 (Debian build 17.0.8+7-1); handle 'B' 
in Java patterns, as it is used in standard patterns now.
---
 .github/workflows/check-for-updates.yml |   2 +-
 .github/workflows/test.yml              |   2 +-
 datetime.el                             |  50 ++++++++++++++++++++++++++++----
 dev/HarvestData.java                    |  41 ++++++++++++++++++++++++++
 locale-data.extmap                      | Bin 278371 -> 349524 bytes
 test/format.el                          |  12 ++++++++
 test/parse.el                           |   3 ++
 timezone-data.extmap                    | Bin 870482 -> 889713 bytes
 timezone-name-data.extmap               | Bin 2760832 -> 2997365 bytes
 9 files changed, 102 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/check-for-updates.yml 
b/.github/workflows/check-for-updates.yml
index 580ee628f5..d5b6957beb 100644
--- a/.github/workflows/check-for-updates.yml
+++ b/.github/workflows/check-for-updates.yml
@@ -27,7 +27,7 @@ jobs:
       uses: actions/setup-java@v2
       with:
         distribution: 'zulu'
-        java-version: '14'
+        java-version: '17'
 
     - name: Check out the source code
       uses: actions/checkout@v2
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0ad0d676fb..9d3a7176bf 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -32,7 +32,7 @@ jobs:
       uses: actions/setup-java@v2
       with:
         distribution: 'zulu'
-        java-version: '14'
+        java-version: '17'
 
     - name: Check out the source code
       uses: actions/checkout@v2
diff --git a/datetime.el b/datetime.el
index 8b2b137c48..6393e27152 100644
--- a/datetime.el
+++ b/datetime.el
@@ -92,6 +92,7 @@
 ;;   weekday-standalone-name (full | abbreviated)
 ;;
 ;;   am-pm (full | abbreviated)
+;;   day-period (short | full | narrow)
 ;;
 ;;   hour-0-23 (NUMBER)
 ;;   hour-1-24 (NUMBER)
@@ -140,6 +141,8 @@
 ;;   - `:eras' and `:am-pm' default to English version;
 ;;   - month/dayweek standalone abbreviations or names default to
 ;;     the corresponding context-aware property;
+;;   - for day period strings, both `:full' and `:narrow' variants
+;;     fall back to `:short';
 ;;   - date-time patterns are not stored, instead they are built from
 ;;     date and time parts for that locale; corresponding field is a
 ;;     cons with car determining what should be in the beginning (t
@@ -381,6 +384,11 @@ form:
                        (?k (cons 'hour-1-24         num-repetitions))
                        (?K (cons 'hour-am-pm-0-11   num-repetitions))
                        (?h (cons 'hour-am-pm-1-12   num-repetitions))
+                       (?B (cons 'day-period        (pcase num-repetitions
+                                                      (1 :short)
+                                                      (4 :full)
+                                                      (5 :narrow)
+                                                      (_ (error "Pattern 
character `%c' must come in exactly 1, 4 or 5 repetitions" character)))))
                        (?m (cons 'minute            num-repetitions))
                        (?s (cons 'second            num-repetitions))
                        (?S (cons 'second-fractional num-repetitions))
@@ -454,6 +462,11 @@ form:
                           (`decimal-separator details)
                           (`second-fractional (cons ?S details))
                           (`am-pm             "a")
+                          (`day-period        (pcase details
+                                                (:short  "B")
+                                                (:full   "BBBB")
+                                                (:narrow "BBBBB")
+                                                (_       (error "Unexpected 
details for `%s' part: %s" type details))))
                           (_                  (error "Unexpected part type %s" 
type)))))
           (push (cond ((integerp string)
                        (string string))
@@ -506,6 +519,14 @@ form:
                                                         (push (setq days (+ 
days month-days)) result))
                                                       (apply #'vector 
(nreverse result))))
 
+;; FIXME: Maybe use binary lookup or something?  Not terribly important.
+(defsubst datetime--day-period-index (thresholds minute)
+  (let ((index 0))
+    (while (and thresholds (<= (car thresholds) minute))
+      (setq thresholds (cdr thresholds)
+            index      (1+ index)))
+    index))
+
 
 (defsubst datetime--digits-format (num-repetitions)
   (if (> num-repetitions 1) (format "%%0%dd" num-repetitions) "%d"))
@@ -616,6 +637,13 @@ to this function.
              (setq need-hour t)
              (push "%s" format-parts)
              (push `(aref ,(datetime-locale-field locale :am-pm) (if (>= hour 
12) 1 0)) format-arguments))
+            (`day-period
+             (setq need-time t)
+             (push "%s" format-parts)
+             (let* ((day-period-data (datetime-locale-field locale 
:day-periods))
+                    (thresholds      (plist-get day-period-data :thresholds))
+                    (strings         (or (plist-get day-period-data details) 
(plist-get day-period-data :short))))
+               (push `(aref ,strings (datetime--day-period-index ',thresholds 
(/ time 60))) format-arguments)))
             ((or `hour-0-23 `hour-1-24 `hour-am-pm-0-11 `hour-am-pm-1-12)
              (setq need-hour t)
              (push (datetime--digits-format details) format-parts)
@@ -950,6 +978,7 @@ unless specified otherwise.
          month-name-part-indices
          day-of-month-part-indices
          am-pm-part-indices
+         day-period-part-indices
          hour-0-23-part-indices
          hour-1-24-part-indices
          hour-am-pm-1-12-part-indices
@@ -1006,6 +1035,10 @@ unless specified otherwise.
                         (`am-pm                (when (or validating (null 
am-pm-part-indices))
                                                  (push part-index 
am-pm-part-indices))
                                                (datetime-locale-field locale 
:am-pm))
+                        (`day-period           (when (or validating (null 
day-period-part-indices))
+                                                 (push part-index 
day-period-part-indices))
+                                               (let ((day-period-data 
(datetime-locale-field locale :day-periods)))
+                                                 (or (plist-get 
day-period-data details) (plist-get day-period-data :short))))
                         (`hour-0-23            (when (or validating (null 
hour-0-23-part-indices))
                                                  (push part-index 
hour-0-23-part-indices))
                                                23)
@@ -1075,6 +1108,7 @@ unless specified otherwise.
           month-name-part-indices        (nreverse month-name-part-indices)
           day-of-month-part-indices      (nreverse day-of-month-part-indices)
           am-pm-part-indices             (nreverse am-pm-part-indices)
+          day-period-part-indices        (nreverse day-period-part-indices)
           hour-0-23-part-indices         (nreverse hour-0-23-part-indices)
           hour-1-24-part-indices         (nreverse hour-1-24-part-indices)
           hour-am-pm-1-12-part-indices   (nreverse 
hour-am-pm-1-12-part-indices)
@@ -1098,7 +1132,7 @@ unless specified otherwise.
     (let* ((regexp-parts            regexp-parts)
            (substituting-indices-in (list era-part-indices
                                           year-part-indices 
month-number-part-indices month-name-part-indices day-of-month-part-indices
-                                          am-pm-part-indices
+                                          am-pm-part-indices 
day-period-part-indices
                                           hour-0-23-part-indices 
hour-1-24-part-indices hour-am-pm-1-12-part-indices hour-am-pm-0-11-part-indices
                                           minute-part-indices 
second-part-indices second-fractional-part-indices))
            (part-index              0)
@@ -1140,6 +1174,7 @@ unless specified otherwise.
            (am-pm-computation  (or (datetime--parser-computation pattern 
"am-pm" validating nil nil (am-pm-part-indices 
(datetime--parser-string-if-computation locale :am-pm downcased 0 12) t))
                                    (plist-get 'am-pm 0)
                                    0))
+           (_day-period-computation)  ;; FIXME: Write; currently not validated 
for consistency with actual time.
            (hour-computation   (or (datetime--parser-computation pattern 
"hour" validating nil 23
                                                                  
(hour-0-23-part-indices datetime--parser-int-computation)
                                                                  
(hour-1-24-part-indices datetime--parser-hour-1-24-computation)
@@ -1368,6 +1403,9 @@ specified otherwise.
                            (datetime-locale-field locale (if (eq details 
'abbreviated) :weekday-standalone-abbr :weekday-standalone-names)))
                           (`am-pm
                            (datetime-locale-field locale :am-pm))
+                          (`day-period
+                           (let ((day-period-data (datetime-locale-field 
locale :day-periods)))
+                             (or (plist-get day-period-data details) 
(plist-get day-period-data :short))))
                           (`hour-0-23            23)
                           (`hour-1-24            24)
                           (`hour-am-pm-0-11      11)
@@ -1468,7 +1506,7 @@ options can affect result of this function."
 OPTIONS are passed to `datetime-recode-pattern'.  Currently no
 options can affect result of this function."
   (datetime--pattern-includes-p type pattern options
-                                am-pm hour-0-23 hour-1-24 hour-am-pm-0-11 
hour-am-pm-1-12 minute second second-fractional))
+                                am-pm day-period hour-0-23 hour-1-24 
hour-am-pm-0-11 hour-am-pm-1-12 minute second second-fractional))
 
 (defun datetime-pattern-includes-era-p (type pattern &rest options)
   "Determine if PATTERN includes the date era.
@@ -1649,7 +1687,7 @@ Supported fields:
   :weekday-standalone-abbr
   :weekday-standalone-names
   :am-pm"
-  ;; Additionally `:date-patterns', `:time-patterns' and
+  ;; Additionally `:day-periods', `:date-patterns', `:time-patterns' and
   ;; `:date-time-pattern-rule' are supported for internal use.
   (let ((data (extmap-get datetime--locale-extmap locale t)))
     (or (datetime--do-get-locale-field data field)
@@ -1698,7 +1736,7 @@ create based on locales `datetime' knows about.
 
 Note that this database doesn't include timezone names.  See
 `datetime-timezone-name-database-version'."
-  4)
+  5)
 
 (defun datetime-timezone-database-version ()
   "Return timezone database version, a simple integer.
@@ -1708,7 +1746,7 @@ create based on timezones `datetime' knows about and 
their rules.
 
 Locale-specific timezone names are contained in a different
 database.  See `datetime-timezone-name-database-version'."
-  6)
+  7)
 
 (defun datetime-timezone-name-database-version ()
   "Return timezone name database version, a simple integer.
@@ -1721,7 +1759,7 @@ Other locale-specific data as well as locale-independent 
data
 about timezones is contained in different databases.  See
 `datetime-locale-database-version' and
 `datetime-timezone-database-version'."
-  3)
+  4)
 
 
 (provide 'datetime)
diff --git a/dev/HarvestData.java b/dev/HarvestData.java
index 41e785230d..7eb866dc55 100644
--- a/dev/HarvestData.java
+++ b/dev/HarvestData.java
@@ -81,6 +81,7 @@ public class HarvestData
             map.put (":weekday-standalone-abbr",  toLispVector (getNames 
(locale, ChronoField.DAY_OF_WEEK,   "ccc",  1, 7)));
             map.put (":weekday-standalone-names", toLispVector (getNames 
(locale, ChronoField.DAY_OF_WEEK,   "cccc", 1, 7)));
             map.put (":am-pm",                    toLispVector (getNames 
(locale, ChronoField.AMPM_OF_DAY,   "a",    0, 1)));
+            map.put (":day-periods",              findDayPeriodData (locale));
 
             Map <String, String>  date_patterns = toPatternPlist ((style) -> 
DateTimeFormatterBuilder.getLocalizedDateTimePattern (style, null, chronology, 
locale));
             Map <String, String>  time_patterns = toPatternPlist ((style) -> 
DateTimeFormatterBuilder.getLocalizedDateTimePattern (null, style, chronology, 
locale));
@@ -194,6 +195,45 @@ public class HarvestData
         return names;
     }
 
+    protected static String findDayPeriodData (Locale locale)
+    {
+        var            time       = LocalDateTime.of (2001, 1, 1, 0, 0, 0);
+        var            formatters = List.of (DateTimeFormatter.ofPattern ("B", 
    locale),
+                                             DateTimeFormatter.ofPattern 
("BBBB",  locale),
+                                             DateTimeFormatter.ofPattern 
("BBBBB", locale));
+        List <String>  strings    = null;
+        var            periods    = new ArrayList <List <String>> ();
+        var            thresholds = new ArrayList <Integer> ();
+
+        // It seems the thresholds are not exposed, so we find them like this.
+        for (int minute = 0; minute < 24 * 60; minute++, time = 
time.plusMinutes (1)) {
+            var  time_       = time;
+            var  new_strings = formatters.stream ().map ((formatter) -> 
formatter.format (time_)).toList ();
+
+            if (!Objects.equals (new_strings, strings)) {
+                periods.add (new_strings);
+                if (minute > 0)
+                    thresholds.add (minute);
+
+                strings = new_strings;
+            }
+        }
+
+        var  data = new LinkedHashMap <String, String> ();
+
+        data.put (":thresholds", toLispList (thresholds));
+        data.put (":short",      toLispVector (periods.stream ().map 
((strings_) -> strings_.get (0)).toList (), true));
+        data.put (":full",       toLispVector (periods.stream ().map 
((strings_) -> strings_.get (1)).toList (), true));
+        data.put (":narrow",     toLispVector (periods.stream ().map 
((strings_) -> strings_.get (2)).toList (), true));
+
+        if (Objects.equals (data.get (":full"), data.get (":short")))
+            data.remove (":full");
+        if (Objects.equals (data.get (":narrow"), data.get (":short")))
+            data.remove (":narrow");
+
+        return toLispPlist (data, false);
+    }
+
     protected static void removeUnnecessaryLocaleData (Map <Locale, Map 
<String, String>> data, Locale locale)
     {
         Map <String, String>  locale_data = data.get (locale);
@@ -212,6 +252,7 @@ public class HarvestData
         removeForFallback1 (locale_data, parent_data, ":decimal-separator",    
  "?.");
         removeForFallback1 (locale_data, parent_data, ":eras",                 
  ENGLISH_ERAS);
         removeForFallback1 (locale_data, parent_data, ":am-pm",                
  ENGLISH_AM_PM);
+        removeForFallback1 (locale_data, parent_data, ":day-periods",          
  null);
         removeForFallback1 (locale_data, parent_data, 
":date-time-pattern-rule", "(t . \" \")");
 
         removeForFallback2 (locale_data, parent_data, 
":month-standalone-abbr",    ":month-context-abbr");
diff --git a/locale-data.extmap b/locale-data.extmap
index cdccd85e21..04bab090b0 100644
Binary files a/locale-data.extmap and b/locale-data.extmap differ
diff --git a/test/format.el b/test/format.el
index faf7b47e23..c31f246aa9 100644
--- a/test/format.el
+++ b/test/format.el
@@ -119,3 +119,15 @@
     ;; Rule-based transition on 2014-10-26.  Should also result in
     ;; timezone name changing between CEST and CET.
     (datetime--test-formatter-around-transition 1414285200)))
+
+(ert-deftest datetime-formatting-day-periods ()
+  (let (times)
+    (dotimes (minute (* 24 60))
+      (push (* minute 60) times))
+    (setf times (nreverse times))
+    (dolist (pattern '("HH:mm:ss B" "HH:mm:ss BBBB" "HH:mm:ss BBBBB"))
+      (datetime--test-set-up-formatter 'UTC 'en pattern
+        (datetime--test-formatter times)))))
+
+
+(provide 'test/format)
diff --git a/test/parse.el b/test/parse.el
index 7084f8eed3..3adf91e4fa 100644
--- a/test/parse.el
+++ b/test/parse.el
@@ -159,3 +159,6 @@
   (dolist (timezone (datetime-list-timezones))
     (datetime--test-set-up-parser timezone 'en "yyyyMMddHHmmss"
       (datetime--test-parser '("20220506123000")))))
+
+
+(provide 'test/parse)
diff --git a/timezone-data.extmap b/timezone-data.extmap
index f0882fe52b..bf074b459f 100644
Binary files a/timezone-data.extmap and b/timezone-data.extmap differ
diff --git a/timezone-name-data.extmap b/timezone-name-data.extmap
index 82eb48f17d..80ab282566 100644
Binary files a/timezone-name-data.extmap and b/timezone-name-data.extmap differ

Reply via email to