summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPatrick McDermott <patrick.mcdermott@libiquity.com>2019-06-15 20:44:32 (EDT)
committer Patrick McDermott <patrick.mcdermott@libiquity.com>2019-06-15 20:44:32 (EDT)
commit431473c45813ba9beb15d123d119fcb1dcd0a97c (patch)
tree10bd1cecd0515aae7451e0de14428e8f08ff07cd /lib
parent51ee91e36b78c224e1b11976a08f01923f6bb7dc (diff)
lib/time.sh: New file
Diffstat (limited to 'lib')
-rw-r--r--lib/local.mk3
-rw-r--r--lib/time.sh162
2 files changed, 164 insertions, 1 deletions
diff --git a/lib/local.mk b/lib/local.mk
index 845905a..dc5b5e8 100644
--- a/lib/local.mk
+++ b/lib/local.mk
@@ -24,7 +24,8 @@ libopkbuild_sources = \
%reldir%/metadata.sh \
%reldir%/control.sh \
%reldir%/changelog.sh \
- %reldir%/deps.sh
+ %reldir%/deps.sh \
+ %reldir%/time.sh
EXTRA_libopkbuild_sources =
libopkbuild_ldadd = $(libopkbuild_sources:.sh=.sho)
libopkbuild_dependencies = $(libopkbuild_ldadd)
diff --git a/lib/time.sh b/lib/time.sh
new file mode 100644
index 0000000..b65bbba
--- /dev/null
+++ b/lib/time.sh
@@ -0,0 +1,162 @@
+# Functions for converting date and time
+#
+# Copyright (C) 2019 Patrick McDermott
+#
+# This file is part of opkbuild.
+#
+# opkbuild is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# opkbuild is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with opkbuild. If not, see <http://www.gnu.org/licenses/>.
+
+_ob_is_leap_year()
+{
+ local year="${1}"
+ shift 1 || _ob_abort
+
+ return $((!(!(${year} % 4) && ${year} % 100 || !(${year} % 400))))
+}
+
+_ob_year_to_days()
+{
+ local year="${1}"
+ shift 1 || _ob_abort
+ local y=1970
+ local d=0
+
+ # Simple but iterative.
+ while [ ${y} -ne ${year} ]; do
+ _ob_is_leap_year ${y} && : $((d += 366)) || : $((d += 365))
+ : $((y += 1))
+ done
+ printf '%d' ${d}
+ return 0
+}
+
+_ob_month_to_days()
+{
+ local month="${1}"
+ local year="${2}"
+ shift 2 || _ob_abort
+ local d=
+
+ case ${month} in
+ 1) d=0;; 2) d=31;; 3) d=59;; 4) d=90;;
+ 5) d=120;; 6) d=151;; 7) d=181;; 8) d=212;;
+ 9) d=243;; 10) d=273;; 11) d=304;; 12) d=334;;
+ esac
+ [ ${month} -ge 2 ] && _ob_is_leap_year ${year} && : $((++d))
+ printf '%d' ${d}
+ return 0
+}
+
+_ob_mktime()
+{
+ local year="${1}"
+ local mon="${2}"
+ local mday="${3}"
+ local hour="${4}"
+ local min="${5}"
+ local sec="${6}"
+ local timezone="${7}"
+ shift 7 || _ob_abort
+ local d=
+ local t=
+
+ d=$(($(_ob_year_to_days ${year}) + $(_ob_month_to_days ${mon} ${year})))
+ d=$((${d} + ${mday} - 1))
+ t=$(( ( (${d} * 24 + ${hour}) * 60 + ${min}) * 60 + ${sec} ))
+ t=$((${t} - ${timezone}))
+ printf '%d' ${t}
+ return 0
+}
+
+## @brief Convert a date and time into seconds since the Epoch
+## @details \fBob_rfc822_mktime\fP() converts date and time formatted according
+## to RFCs 822, 2822, and 5322 into non-leap seconds elapsed since the
+## Epoch. It is similar to the C function \fBmktime\fP() except that
+## it accepts a formatted string instead of a structure as its
+## argument. It is intended to parse \fIchangelog\fP dates into a time
+## value usable in the \fISOURCE_DATE_EPOCH\fP environment variable.
+## @operand rfc822_tm req A date and time string formatted according to the
+## \fIdate-time\fP symbol of RFC 5322 section 3.3.
+## @return Returns 0.
+## @stdout Prints the number of non-leap seconds elapsed since the Epoch.
+## @pure yes This function has no side effects.
+ob_rfc822_mktime()
+{
+ local rfc822_tm="${1}"
+ shift 1 || _ob_abort
+ local wday=
+ local mday=
+ local mon=
+ local year=
+ local hour=
+ local min=
+ local sec=
+ local tz=
+ local tzsgn=
+ local tzhour=
+ local tzmin=
+
+ read wday mday mon year hour min sec tz <<-EOF
+ ${rfc822_tm}
+ EOF
+ tzsgn="${tz%%[0-9]*}"; tz=${tz#[+-]}; tz=${tz#0}; tz=${tz#0}
+ tzhour=$((${tz} / 100))
+ tzmin=$(( ${tz} % 100))
+ _ob_mktime ${year} ${mon#0} ${mday#0} ${hour#0} ${min#0} ${sec#0} \
+ $((${tzsgn}1 * (${tzhour} * 60 + ${tzmin}) * 60))
+ return 0
+}
+
+## @brief Convert seconds since the Epoch into a date and time
+## @details \fBob_iso8601_gmtime\fP() converts the number of non-leap seconds
+## elapsed since the Epoch into date and time in UTC formatted
+## according to ISO 8601. It is similar to the C function \fBgmtime\fP
+## except that it returns a formatted string instead of a structure.
+## It is intended to generate a date and time usable with a
+## POSIX-conformant \fBtouch\fP utility.
+## @operand timep req The number of non-leap seconds elapsed since the Epoch.
+## @return Returns 0.
+## @stdout Prints the date and time in UTC formatted according to ISO 8601.
+## @pure yes This function has no side effects.
+ob_iso8601_gmtime()
+{
+ local timep="${1}"
+ shift 1 || _ob_abort
+ local sec=
+ local min=
+ local hour=
+ local days_in_year=
+ local year=1970
+ local mon=1
+ local mday=
+
+ sec=$((${timep} % 60)); : $((timep /= 60))
+ min=$((${timep} % 60)); : $((timep /= 60))
+ hour=$((${timep} % 24)); : $((timep /= 24))
+
+ while :; do
+ _ob_is_leap_year ${year} && days_in_year=366 || days_in_year=365
+ [ ${timep} -le ${days_in_year} ] && break
+ : $((timep -= ${days_in_year}))
+ : $((year += 1))
+ done
+ while [ ${timep} -gt $(_ob_month_to_days $((${mon} + 1)) ${year}) ]; do
+ : $((mon += 1))
+ done
+ mday=$((${timep} - $(_ob_month_to_days ${mon} ${year}) + 1))
+
+ printf '%04d-%02d-%02dT%02d:%02d:%02dZ' \
+ ${year} ${mon} ${mday} ${hour} ${min} ${sec}
+ return 0
+}