In [1]:
from datetime import timedelta, datetime, time
import helper
import pytz
from dateutil.parser import parse
from matplotlib import ticker
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
import ephem

In [2]:
%matplotlib inline

Setup

Here we set up place and time_zone of observation point. Then set up the start date.


In [3]:
place = 'Moscow'
time_zone = 'Europe/Moscow'
base_date = '2014.01.01'

In [4]:
tz = pytz.timezone(time_zone)
bdate = parse(base_date)
bdate_tz = tz.localize(bdate)

In [5]:
observer = ephem.city(place)
sun = ephem.Sun()

In [6]:
dates = pd.DataFrame(columns=['sunrise', 'transit', 'sunset'])

In [7]:
for date in pd.Series(pd.date_range(bdate_tz, periods=365, freq='D')):
    observer.date = date.astimezone(pytz.utc)
    sun.compute(observer)
    
    bare_date = date.date()
    
    sunrise_dt = observer.next_rising(ephem.Sun()).datetime()
    sunrise_dt = pytz.utc.localize(sunrise_dt).astimezone(tz)   
    dates.sunrise[bare_date] = sunrise_dt
    
    transit_dt = observer.next_transit(ephem.Sun()).datetime()
    transit_dt = pytz.utc.localize(transit_dt).astimezone(tz)
    dates.transit[bare_date] = transit_dt
    
    sunset_dt = observer.next_setting(ephem.Sun()).datetime()
    sunset_dt = pytz.utc.localize(sunset_dt).astimezone(tz) 
    dates.sunset[bare_date] = sunset_dt

Calculations of daylight time

  • Blue-filled shape is daylight time each day during a year.
  • Borders of blue-filled shape are sunset and sunrise times.
  • Red line is zenith.
  • Red dots are solstices (extrema).

In [8]:
minmax_sx = [dates.sunrise.loc[dates.sunrise.dt.time == dates.sunrise.dt.time.min()], 
          dates.sunrise.loc[dates.sunrise.dt.time == dates.sunrise.dt.time.max()],
          dates.sunset.loc[dates.sunset.dt.time == dates.sunset.dt.time.min()], 
          dates.sunset.loc[dates.sunset.dt.time == dates.sunset.dt.time.max()]]
minmax_sx_df = pd.concat(minmax_sx)

fig, ax = plt.subplots(figsize=(12,8))
fig.autofmt_xdate()
ax.grid(True)
ax.fill_between(x=dates.sunrise.index, y1=dates.sunrise.dt.time.values, y2=dates.sunset.dt.time.values, alpha=.4)
ax.plot(dates.sunrise.index, dates.transit.dt.time, 'r')
for date, val in minmax_sx_df.iteritems():
    ax.annotate(str(date), xy=[date, val.time()])
ax.plot(minmax_sx_df.index, minmax_sx_df.dt.time, 'ro')


Out[8]:
[<matplotlib.lines.Line2D at 0x1127cce50>]

Zenith

Magnified zenith line from previous figure.


In [9]:
fig, ax = plt.subplots(figsize=(12,8))
fig.autofmt_xdate()
ax.grid(True)
ax.plot(dates.transit.index, dates.transit.dt.time, 'r')


Out[9]:
[<matplotlib.lines.Line2D at 0x112bd6810>]

Length of day

Changing of day length during a year.


In [10]:
daylengths = dates.sunset - dates.sunrise

minmax_dl = [daylengths.loc[daylengths == daylengths.min()], 
             daylengths.loc[daylengths == daylengths.max()]]
minmax_dl_df = pd.concat(minmax_dl)

fig, ax = plt.subplots(figsize=(12,8))
fig.autofmt_xdate()
ax.grid(True)
ax.yaxis.set_major_formatter(ticker.FuncFormatter(helper.timedelta_formatter))
ax.plot(daylengths.index, daylengths, 'b')
# for date, val in minmax_dl_df.iteritems():
#     val += datetime(1970, 1, 1)
#     ax.annotate(str(date), xy=[date, val.time()])
ax.plot(minmax_dl_df.index, minmax_dl_df, 'ro')


Out[10]:
[<matplotlib.lines.Line2D at 0x112caf450>]

Changing of day length

Derivative of day length during a year.


In [11]:
diffs = (dates.sunset - dates.sunrise).diff(1)[1:]
baseline = pd.Series([timedelta(seconds=0)], index=diffs.index)

fig, ax = plt.subplots(figsize=(12,8))
ax.grid(True)
fig.autofmt_xdate()
ax.fill_between(x=diffs.index, y1=pd.to_datetime(baseline.values), y2=diffs.values, alpha=.4)
ax.yaxis.set_major_formatter(ticker.FuncFormatter(helper.timedelta_as_dt_formatter))



In [ ]: