From 4a73ba328f374320ee36a77439b7c4fd58d5b84c Mon Sep 17 00:00:00 2001
From: Mattias Andrée <maandree@kth.se>
Date: Sat, 20 Feb 2021 00:40:19 +0100
Subject: m + improve makefile
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Mattias Andrée <maandree@kth.se>
---
 .gitignore |   9 +-
 Makefile   |  52 ++++-----
 blue       | 357 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 blue.py    | 357 -------------------------------------------------------------
 4 files changed, 378 insertions(+), 397 deletions(-)
 create mode 100755 blue
 delete mode 100755 blue.py

diff --git a/.gitignore b/.gitignore
index 33533be..f64de1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,5 @@
-\#*\#
+*\#*
 *~
 __pycache__/
-*.swp
-*.swo
-*.bak
 *.pyc
 *.pyo
-*.orig
-bin/
-aux/
-obj/
diff --git a/Makefile b/Makefile
index f0d87a4..1589ccf 100644
--- a/Makefile
+++ b/Makefile
@@ -1,38 +1,26 @@
-PREFIX = /usr
-BINDIR = $(PREFIX)/bin
-DATADIR = $(PREFIX)/share
-MANDIR = $(DATADIR)/man
-LICENSEDIR = $(DATADIR)/license
+.POSIX:
 
-PKGNAME = blue
-COMMAND = blue
+PREFIX    = /usr
+MANPREFIX = $(PREFIX)/share/man
 
 all:
-clean:
-
-install: install-cmd install-doc install-license
-install-doc: install-man
-
-install-cmd:
-	mkdir -p -- "$(DESTDIR)$(BINDIR)"
-	cp -- blue.py "$(DESTDIR)$(BINDIR)/$(COMMAND)"
-	chmod 0755 -- "$(DESTDIR)$(BINDIR)/$(COMMAND)"
+	@:
+
+install:
+	mkdir -p -- "$(DESTDIR)$(PREFIX)/bin"
+	mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1"
+	mkdir -p -- "$(DESTDIR)$(PREFIX)/share/licenses/blue"
+	cp -- blue "$(DESTDIR)$(PREFIX)/bin/"
+	cp -- blue.1 "$(DESTDIR)$(MANDIR)/man1/"
+	cp -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/blue/"
+
+uninstall:
+	-rm -f -- "$(DESTDIR)$(PREFIX)/bin/blue"
+	-rm -f -- blue.1 "$(DESTDIR)$(MANPREFIX)/man1/blue.1"
+	-rm -f -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/blue/LICENSE"
+	-rmdir -- LICENSE "$(DESTDIR)$(PREFIX)/share/licenses/blue"
 
-install-man:
-	mkdir -p -- "$(DESTDIR)$(MANDIR)/man1"
-	cp -- blue.py "$(DESTDIR)$(MANDIR)/man1/$(COMMAND).1"
-	chmod 0644 -- "$(DESTDIR)$(MANDIR)/man1/$(COMMAND).1"
-
-install-license:
-	mkdir -p -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
-	cp -- LICENSE "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE"
-	chmod 0644 -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE"
-
-uninstall:	
-	-rm -- "$(DESTDIR)$(BINDIR)/$(COMMAND)"
-	-rm -- "$(DESTDIR)$(MANDIR)/man1/$(COMMAND).1"
-	-rm -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)/LICENSE"
-	-rmdir -- "$(DESTDIR)$(LICENSEDIR)/$(PKGNAME)"
+clean:
+	@:
 
 .PHONY: all install uninstall clean
-.PHONY: install-cmd install-doc install-man install-license
diff --git a/blue b/blue
new file mode 100755
index 0000000..a10e3e8
--- /dev/null
+++ b/blue
@@ -0,0 +1,357 @@
+#!/usr/bin/env python3
+# See LICENSE file for copyright and license details.
+
+import sys, os, pwd, time
+import solar_python as sol
+
+
+loc = None
+stop_date = None
+human = False
+unix = False
+local = False
+noon = False
+night = False
+blue = False
+gold = False
+unblue = False
+ungold = False
+morning = []
+evening = []
+dderiv = []
+nderiv = []
+res = '1s'
+
+
+## Parse command line
+argv0 = sys.argv[0] if len(sys.argv) > 0 else 'blue'
+def usage():
+    opts  =  '[-d delev]* [-D delev]* [-e elev]* [-m elev]* [-h [-L] | -u | -L]'
+    opts += ' [-l lat:lon | -l loc] [-s year-month-day | -s -] [-r num[h|m|s]]'
+    opts += ' [-bBgGnN]'
+    print('Usage: %s %s' % (argv0, opts), file = sys.stderr)
+    sys.exit(1)
+i, n = 1, len(sys.argv)
+def getarg():
+    global i, j, n, m
+    if j < m:
+        rc = arg[j:]
+        j = m
+        return rc
+    else:
+        j = m
+        i += 1
+        if i == n:
+            usage()
+        return sys.argv[i]
+while i < n:
+    arg = sys.argv[i]
+    if arg == '--':
+        i += 1
+        break
+    elif arg.startswith('-'):
+        j, m = 1, len(arg)
+        while j < m:
+            c = arg[j]
+            j += 1
+            if c == 'd':
+                dderiv.append(getarg())
+            elif c == 'D':
+                nderiv.append(getarg())
+            elif c == 'e':
+                evening.append(getarg())
+            elif c == 'm':
+                morning.append(getarg())
+            elif c == 'l':
+                loc = getarg()
+            elif c == 's':
+                stop_date = getarg()
+            elif c == 'r':
+                res = getarg()
+            elif c == 'b':
+                blue = True
+            elif c == 'B':
+                unblue = True
+            elif c == 'g':
+                gold = True
+            elif c == 'G':
+                ungold = True
+            elif c == 'h':
+                human = True
+            elif c == 'u':
+                unix = True
+            elif c == 'L':
+                local = True
+            elif c == 'n':
+                noon = True
+            elif c == 'N':
+                night = True
+            else:
+                usage()
+        i += 1
+    else:
+        break
+if i != n or (human and unix) or (local and unix):
+    usage()
+
+
+## Parse resolution
+if len(res) < 2:
+    usage()
+mul = {'s' : 1.0, 'm' : 60.0, 'h' : 60 * 60.0}
+suffix = res[-1]
+value = res[:-1]
+if '.' in value:
+    usage()
+try:
+    res = int(value) * mul[suffix]
+except:
+    usage()
+
+
+## Parse elevations
+try:
+    evening = [float(e) for e in evening]
+    morning = [float(e) for e in morning]
+    dderiv  = [float(e) for e in dderiv]
+    nderiv  = [float(e) for e in nderiv]
+    for e in evening + morning:
+        if abs(e) > 90:
+            usage()
+except:
+    usage()
+
+
+## Parse -bBgGnN
+if blue:
+    morning.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[0])
+    evening.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[1])
+if unblue:
+    morning.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[1])
+    evening.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[0])
+if gold:
+    morning.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[0])
+    evening.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[1])
+if ungold:
+    morning.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[1])
+    evening.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[0])
+if noon:
+    dderiv.append(0.0)
+if night:
+    nderiv.append(0.0)
+
+
+## Fallback options
+if len(morning) == 0 and len(evening) == 0 and len(dderiv) == 0 and len(nderiv) == 0:
+    morning.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[0])
+    evening.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[1])
+
+
+## Get geolocation
+def get_geolocation_from_conf(filename, ispath = False):
+    filenames, lat, lon = [], None, None
+    if ispath:
+        filenames.append(filename)
+    else:
+        if 'HOME' in os.environ and len(os.environ['HOME']) > 0:
+            filenames.append(os.environ['HOME'] + '/.config/' + filename)
+        try:
+            filenames.append(pwd.getpwuid(os.getuid()).pw_dir + '/.config/' + filename)
+        except:
+            pass
+        filenames.append('/etc/' + filename)
+    for filename in filenames:
+        try:
+            with open(filename, 'rb') as file:
+                loc = file.read().decode('utf-8', 'replace').split('\n')[0]
+            (lat, lon) = loc.split(' ')
+            lat, lon = float(lat), float(lon)
+            break
+        except:
+            lat, lon = None, None
+    return (lat, lon)
+if loc is not None:
+    try:
+        (lat, lon) = loc.split(':')
+        lat = float(lat)
+        lon = float(lon)
+        if (abs(lat) > 90 or abs(lon) > 180):
+            lat = None
+    except:
+        lat = None
+    if lat is None:
+        if loc.startswith('./') or loc.startswith('../') or loc.startswith('/'):
+            locfile = loc
+        else:
+            locfile = 'geolocation.d/' + loc
+        (lat, lon) = get_geolocation_from_conf(locfile, locfile is loc)
+    if lat is None:
+        print('%s: bad location: %s' % (argv0, loc), file = sys.stderr)
+        sys.exit(1)
+else:
+    (lat, lon) = get_geolocation_from_conf('geolocation')
+    if lat is None:
+        print('%s: no geolocation set' % argv0, file = sys.stderr)
+        sys.exit(1)
+
+
+## Parse stop date
+if stop_date is not None:
+    if stop_date == '-':
+        stop_date = ...
+    else:
+        try:
+            tm = time.strptime(stop_date, '%Y-%m-%d')
+            stop_date = (tm.tm_year, tm.tm_mon, tm.tm_mday)
+        except:
+            usage()
+else:
+    tm = time.localtime()
+    if tm.tm_mon < 12:
+        y, m, d = tm.tm_year, tm.tm_mon + 1, tm.tm_mday - 1
+    else:
+        y, m, d = tm.tm_year + 1, 1, tm.tm_mday - 1
+    if d < 1:
+        m -= 1
+        if m < 1:
+            m = 12
+            y -= 1
+        days = 29 if y % 400 == 0 or (y % 4 == 0 and not y % 100 == 0) else 28
+        days = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+        d = days[m - 1]
+    else:
+        days = 29 if y % 400 == 0 or (y % 4 == 0 and not y % 100 == 0) else 28
+        days = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+        if d > days[m - 1]:
+            d = days[m - 1]
+    stop_date = (y, m, d)
+
+
+## Get stop time
+if stop_date is ...:
+    stop_time = None
+else:
+    stop_time = '%i-%02i-%02i 12:00:00' % stop_date
+    guessed = time.mktime(time.strptime(stop_time, '%Y-%m-%d %H:%M:%S'))
+    is_summer = False
+    for tzname, summer in zip(time.tzname, (False, True)):
+        if time.mktime(time.strptime('%s %s' % (stop_time, tzname), '%Y-%m-%d %H:%M:%S %Z')) == guessed:
+            is_summer = summer
+            break
+    (y, m, d) = stop_date
+    days = 29 if y % 400 == 0 or (y % 4 == 0 and not y % 100 == 0) else 28
+    days = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+    stop_time = d - 1
+    for i in range(m - 1):
+        stop_time += days[i]
+    y -= 1
+    stop_time +=    y * 365 +    y // 4 -    y // 100 +    y // 400
+    stop_time -= 1969 * 365 + 1969 // 4 - 1969 // 100 + 1969 // 400
+    stop_time *= 24 * 60 * 60
+    stop_time += 24 * 60 * 60
+    stop_time -= (time.altzone if is_summer else time.timezone)
+
+
+def get_elev(elev, start, morning):
+    end = start + 0.0099
+    while start < end:
+        rc = sol.future_elevation(lat, lon, elev, start)
+        if rc is None:
+            return (None, end)
+        else:
+            start = rc + 1e-06
+            d  = sol.solar_elevation(lat, lon, rc + 3e-09)
+            d -= sol.solar_elevation(lat, lon, rc)
+            if d >= 0 if morning else d <= 0:
+                return (sol.julian_centuries_to_epoch(rc), start)
+    return (None, end)
+
+def get_deriv(delev, start, daytime):
+    end = start + 0.0099
+    while start < end:
+        rc = sol.future_elevation_derivative(lat, lon, delev, start)
+        if rc is None:
+            return (None, end)
+        else:
+            start = rc + 1e-06
+            elev = sol.solar_elevation(lat, lon, rc)
+            if elev >= 0 if daytime else elev <= 0:
+                return (sol.julian_centuries_to_epoch(rc), start)
+    return (None, end)
+
+def get_morning(elev, start):
+    return get_elev(elev, start, True)
+
+def get_evening(elev, start):
+    return get_elev(elev, start, False)
+
+def get_day(delev, start):
+    return get_deriv(delev, start, True)
+
+def get_night(delev, start):
+    return get_deriv(delev, start, False)
+
+now = sol.epoch_to_julian_centuries(time.time())
+class State:
+    def __init__(self, val, fun):
+        self.start = now
+        self.val = val
+        self.fun = fun
+    def next(self):
+        (rc, self.start) = self.fun(self.val, self.start)
+        return (rc, self.start)
+
+morning = [State(v, get_morning) for v in morning]
+evening = [State(v, get_evening) for v in evening]
+dderiv  = [State(v, get_day)     for v in dderiv]
+nderiv  = [State(v, get_night)   for v in nderiv]
+states  = morning + evening + dderiv + nderiv
+
+
+# So we can stop of the pipe breaks (useful with -s -)
+def print(msg):
+    msg = (str(msg) + '\n').encode('utf-8')
+    ptr, n = 0, len(msg)
+    while ptr < n:
+        ptr += os.write(1, msg[ptr:])
+
+def parse_time(t, localtime, tzname):
+    tm = time.localtime(t) if localtime else time.gmtime(t)
+    if localtime and tm.tm_isdst < 0:
+        tm = time.gmtime(t)
+        localtime = False
+    if not localtime:
+        tz = 'UTC' if tzname else 'Z'
+    else:
+        tz = time.strftime('%Z' if tzname else '%z', tm)
+    return (tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tz)
+
+jc_stop_time = sol.epoch_to_julian_centuries(stop_time) if stop_time is not None else None
+months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
+try:
+    while len(states) > 0:
+        n = len(states)
+        i = 0
+        while i < n:
+            (t, s) = states[i].next()
+            if t is not None and (stop_time is None or t < stop_time):
+                t = int(t / res + 0.5) * res
+                if unix:
+                    print(int(t))
+                else:
+                    t = parse_time(t, local, human)
+                    if human:
+                        (y, m, d, H, M, S, z) = t
+                        t = (y, m, months[m - 1], d, H, M, S, z)
+                        print('%i-(%02i)%s-%02i %02i:%02i:%02i %s' % t)
+                    else:
+                        print('%i-%02i-%02iT%02i:%02i:%02i%s' % t)
+            if jc_stop_time is not None and s >= jc_stop_time:
+                del states[i]
+                n -= 1
+            else:
+                i += 1
+except KeyboardInterrupt as e:
+    sys.exit(0)
+except BrokenPipeError as e:
+    sys.exit(0)
diff --git a/blue.py b/blue.py
deleted file mode 100755
index a10e3e8..0000000
--- a/blue.py
+++ /dev/null
@@ -1,357 +0,0 @@
-#!/usr/bin/env python3
-# See LICENSE file for copyright and license details.
-
-import sys, os, pwd, time
-import solar_python as sol
-
-
-loc = None
-stop_date = None
-human = False
-unix = False
-local = False
-noon = False
-night = False
-blue = False
-gold = False
-unblue = False
-ungold = False
-morning = []
-evening = []
-dderiv = []
-nderiv = []
-res = '1s'
-
-
-## Parse command line
-argv0 = sys.argv[0] if len(sys.argv) > 0 else 'blue'
-def usage():
-    opts  =  '[-d delev]* [-D delev]* [-e elev]* [-m elev]* [-h [-L] | -u | -L]'
-    opts += ' [-l lat:lon | -l loc] [-s year-month-day | -s -] [-r num[h|m|s]]'
-    opts += ' [-bBgGnN]'
-    print('Usage: %s %s' % (argv0, opts), file = sys.stderr)
-    sys.exit(1)
-i, n = 1, len(sys.argv)
-def getarg():
-    global i, j, n, m
-    if j < m:
-        rc = arg[j:]
-        j = m
-        return rc
-    else:
-        j = m
-        i += 1
-        if i == n:
-            usage()
-        return sys.argv[i]
-while i < n:
-    arg = sys.argv[i]
-    if arg == '--':
-        i += 1
-        break
-    elif arg.startswith('-'):
-        j, m = 1, len(arg)
-        while j < m:
-            c = arg[j]
-            j += 1
-            if c == 'd':
-                dderiv.append(getarg())
-            elif c == 'D':
-                nderiv.append(getarg())
-            elif c == 'e':
-                evening.append(getarg())
-            elif c == 'm':
-                morning.append(getarg())
-            elif c == 'l':
-                loc = getarg()
-            elif c == 's':
-                stop_date = getarg()
-            elif c == 'r':
-                res = getarg()
-            elif c == 'b':
-                blue = True
-            elif c == 'B':
-                unblue = True
-            elif c == 'g':
-                gold = True
-            elif c == 'G':
-                ungold = True
-            elif c == 'h':
-                human = True
-            elif c == 'u':
-                unix = True
-            elif c == 'L':
-                local = True
-            elif c == 'n':
-                noon = True
-            elif c == 'N':
-                night = True
-            else:
-                usage()
-        i += 1
-    else:
-        break
-if i != n or (human and unix) or (local and unix):
-    usage()
-
-
-## Parse resolution
-if len(res) < 2:
-    usage()
-mul = {'s' : 1.0, 'm' : 60.0, 'h' : 60 * 60.0}
-suffix = res[-1]
-value = res[:-1]
-if '.' in value:
-    usage()
-try:
-    res = int(value) * mul[suffix]
-except:
-    usage()
-
-
-## Parse elevations
-try:
-    evening = [float(e) for e in evening]
-    morning = [float(e) for e in morning]
-    dderiv  = [float(e) for e in dderiv]
-    nderiv  = [float(e) for e in nderiv]
-    for e in evening + morning:
-        if abs(e) > 90:
-            usage()
-except:
-    usage()
-
-
-## Parse -bBgGnN
-if blue:
-    morning.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[0])
-    evening.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[1])
-if unblue:
-    morning.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[1])
-    evening.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[0])
-if gold:
-    morning.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[0])
-    evening.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[1])
-if ungold:
-    morning.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[1])
-    evening.append(sol.SOLAR_ELEVATION_RANGE_GOLDEN_HOUR[0])
-if noon:
-    dderiv.append(0.0)
-if night:
-    nderiv.append(0.0)
-
-
-## Fallback options
-if len(morning) == 0 and len(evening) == 0 and len(dderiv) == 0 and len(nderiv) == 0:
-    morning.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[0])
-    evening.append(sol.SOLAR_ELEVATION_RANGE_BLUE_HOUR[1])
-
-
-## Get geolocation
-def get_geolocation_from_conf(filename, ispath = False):
-    filenames, lat, lon = [], None, None
-    if ispath:
-        filenames.append(filename)
-    else:
-        if 'HOME' in os.environ and len(os.environ['HOME']) > 0:
-            filenames.append(os.environ['HOME'] + '/.config/' + filename)
-        try:
-            filenames.append(pwd.getpwuid(os.getuid()).pw_dir + '/.config/' + filename)
-        except:
-            pass
-        filenames.append('/etc/' + filename)
-    for filename in filenames:
-        try:
-            with open(filename, 'rb') as file:
-                loc = file.read().decode('utf-8', 'replace').split('\n')[0]
-            (lat, lon) = loc.split(' ')
-            lat, lon = float(lat), float(lon)
-            break
-        except:
-            lat, lon = None, None
-    return (lat, lon)
-if loc is not None:
-    try:
-        (lat, lon) = loc.split(':')
-        lat = float(lat)
-        lon = float(lon)
-        if (abs(lat) > 90 or abs(lon) > 180):
-            lat = None
-    except:
-        lat = None
-    if lat is None:
-        if loc.startswith('./') or loc.startswith('../') or loc.startswith('/'):
-            locfile = loc
-        else:
-            locfile = 'geolocation.d/' + loc
-        (lat, lon) = get_geolocation_from_conf(locfile, locfile is loc)
-    if lat is None:
-        print('%s: bad location: %s' % (argv0, loc), file = sys.stderr)
-        sys.exit(1)
-else:
-    (lat, lon) = get_geolocation_from_conf('geolocation')
-    if lat is None:
-        print('%s: no geolocation set' % argv0, file = sys.stderr)
-        sys.exit(1)
-
-
-## Parse stop date
-if stop_date is not None:
-    if stop_date == '-':
-        stop_date = ...
-    else:
-        try:
-            tm = time.strptime(stop_date, '%Y-%m-%d')
-            stop_date = (tm.tm_year, tm.tm_mon, tm.tm_mday)
-        except:
-            usage()
-else:
-    tm = time.localtime()
-    if tm.tm_mon < 12:
-        y, m, d = tm.tm_year, tm.tm_mon + 1, tm.tm_mday - 1
-    else:
-        y, m, d = tm.tm_year + 1, 1, tm.tm_mday - 1
-    if d < 1:
-        m -= 1
-        if m < 1:
-            m = 12
-            y -= 1
-        days = 29 if y % 400 == 0 or (y % 4 == 0 and not y % 100 == 0) else 28
-        days = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-        d = days[m - 1]
-    else:
-        days = 29 if y % 400 == 0 or (y % 4 == 0 and not y % 100 == 0) else 28
-        days = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-        if d > days[m - 1]:
-            d = days[m - 1]
-    stop_date = (y, m, d)
-
-
-## Get stop time
-if stop_date is ...:
-    stop_time = None
-else:
-    stop_time = '%i-%02i-%02i 12:00:00' % stop_date
-    guessed = time.mktime(time.strptime(stop_time, '%Y-%m-%d %H:%M:%S'))
-    is_summer = False
-    for tzname, summer in zip(time.tzname, (False, True)):
-        if time.mktime(time.strptime('%s %s' % (stop_time, tzname), '%Y-%m-%d %H:%M:%S %Z')) == guessed:
-            is_summer = summer
-            break
-    (y, m, d) = stop_date
-    days = 29 if y % 400 == 0 or (y % 4 == 0 and not y % 100 == 0) else 28
-    days = [31, days, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-    stop_time = d - 1
-    for i in range(m - 1):
-        stop_time += days[i]
-    y -= 1
-    stop_time +=    y * 365 +    y // 4 -    y // 100 +    y // 400
-    stop_time -= 1969 * 365 + 1969 // 4 - 1969 // 100 + 1969 // 400
-    stop_time *= 24 * 60 * 60
-    stop_time += 24 * 60 * 60
-    stop_time -= (time.altzone if is_summer else time.timezone)
-
-
-def get_elev(elev, start, morning):
-    end = start + 0.0099
-    while start < end:
-        rc = sol.future_elevation(lat, lon, elev, start)
-        if rc is None:
-            return (None, end)
-        else:
-            start = rc + 1e-06
-            d  = sol.solar_elevation(lat, lon, rc + 3e-09)
-            d -= sol.solar_elevation(lat, lon, rc)
-            if d >= 0 if morning else d <= 0:
-                return (sol.julian_centuries_to_epoch(rc), start)
-    return (None, end)
-
-def get_deriv(delev, start, daytime):
-    end = start + 0.0099
-    while start < end:
-        rc = sol.future_elevation_derivative(lat, lon, delev, start)
-        if rc is None:
-            return (None, end)
-        else:
-            start = rc + 1e-06
-            elev = sol.solar_elevation(lat, lon, rc)
-            if elev >= 0 if daytime else elev <= 0:
-                return (sol.julian_centuries_to_epoch(rc), start)
-    return (None, end)
-
-def get_morning(elev, start):
-    return get_elev(elev, start, True)
-
-def get_evening(elev, start):
-    return get_elev(elev, start, False)
-
-def get_day(delev, start):
-    return get_deriv(delev, start, True)
-
-def get_night(delev, start):
-    return get_deriv(delev, start, False)
-
-now = sol.epoch_to_julian_centuries(time.time())
-class State:
-    def __init__(self, val, fun):
-        self.start = now
-        self.val = val
-        self.fun = fun
-    def next(self):
-        (rc, self.start) = self.fun(self.val, self.start)
-        return (rc, self.start)
-
-morning = [State(v, get_morning) for v in morning]
-evening = [State(v, get_evening) for v in evening]
-dderiv  = [State(v, get_day)     for v in dderiv]
-nderiv  = [State(v, get_night)   for v in nderiv]
-states  = morning + evening + dderiv + nderiv
-
-
-# So we can stop of the pipe breaks (useful with -s -)
-def print(msg):
-    msg = (str(msg) + '\n').encode('utf-8')
-    ptr, n = 0, len(msg)
-    while ptr < n:
-        ptr += os.write(1, msg[ptr:])
-
-def parse_time(t, localtime, tzname):
-    tm = time.localtime(t) if localtime else time.gmtime(t)
-    if localtime and tm.tm_isdst < 0:
-        tm = time.gmtime(t)
-        localtime = False
-    if not localtime:
-        tz = 'UTC' if tzname else 'Z'
-    else:
-        tz = time.strftime('%Z' if tzname else '%z', tm)
-    return (tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tz)
-
-jc_stop_time = sol.epoch_to_julian_centuries(stop_time) if stop_time is not None else None
-months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
-try:
-    while len(states) > 0:
-        n = len(states)
-        i = 0
-        while i < n:
-            (t, s) = states[i].next()
-            if t is not None and (stop_time is None or t < stop_time):
-                t = int(t / res + 0.5) * res
-                if unix:
-                    print(int(t))
-                else:
-                    t = parse_time(t, local, human)
-                    if human:
-                        (y, m, d, H, M, S, z) = t
-                        t = (y, m, months[m - 1], d, H, M, S, z)
-                        print('%i-(%02i)%s-%02i %02i:%02i:%02i %s' % t)
-                    else:
-                        print('%i-%02i-%02iT%02i:%02i:%02i%s' % t)
-            if jc_stop_time is not None and s >= jc_stop_time:
-                del states[i]
-                n -= 1
-            else:
-                i += 1
-except KeyboardInterrupt as e:
-    sys.exit(0)
-except BrokenPipeError as e:
-    sys.exit(0)
-- 
cgit v1.2.3-70-g09d2