This is great I love it! Wondering if you would consider extending it slightly with 2 additional tags?
historical_min_avg historical_max_avg As mentioned earlier Probably only useful if your database covers many years. I have done so on my local copy and like it because I can now produce output like this: *Today's Climatological Summary* Climatological Period 2006 To 2019 Normal High Temp 52.7°F Normal Low Temp 35.6°F Normal Avg Temp 43.9°F Record High Temp 66.0°F in 2013 Record Low Temp 26.1°F in 2011 Attached are my changes. Please note I have tested it with sqlite , it seems to produce sane expected results. Not test with mysql. Thanks, Paul On Monday, April 6, 2020 at 8:49:42 PM UTC-4, Tom Keffer wrote: > > Relief! I was hoping there wasn't something subtle that I was missing. > > On Mon, Apr 6, 2020 at 5:38 PM Vince Skahan <[email protected] > <javascript:>> wrote: > >> >> I can confirm this is what was happening.... >> Set my VM to PDT and rebuilt daily and the right results are coming out >> now. >> Thanks Tom ! >> >> On Sunday, April 5, 2020 at 4:33:24 PM UTC-7, Tom Keffer wrote: >>> >>> That's what I'm thinking. It recorded the high for UTC day 6-Apr-2007, >>> not local day. >>> >>> On Sun, Apr 5, 2020 at 3:52 PM Vince Skahan <[email protected]> wrote: >>> >>>> It probably more than likely that when I ran rebuild daily after >>>> extending my schema for v4 that the vm I did that on was utc and running >>>> off old archive data that was in PDT. >>>> >>>> Given the UTC-8 here, if the high was after 4pm local (not unusual) >>>> wouldn't that be a day offset? Or would it be the other day off ? Darn >>>> timezones... >>>> >>>>> >>>>>>> -- >> You received this message because you are subscribed to the Google Groups >> "weewx-development" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/weewx-development/1e8fa790-5373-4459-81b8-da128f4a10c2%40googlegroups.com >> >> <https://groups.google.com/d/msgid/weewx-development/1e8fa790-5373-4459-81b8-da128f4a10c2%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "weewx-development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/weewx-development/8cbeb74f-0de9-455f-87e2-6dd99b5c1971%40googlegroups.com.
# # Copyright (c) 2020 Tom Keffer <[email protected]> # # See the file LICENSE.txt for your full rights. # """A WeeWX extension that calculates historical highs, lows for a date, and the times they occurred.""" import datetime import weedb import weewx.units import weewx.xtypes from weewx.engine import StdService from weeutil.weeutil import isStartOfDay VERSION = "0.20" # We have to add this to the collection of special aggregation types that change the unit. For example, asking for the # time of a minimum temperature returns something in group_time, not group_temperature. weewx.units.agg_group['historical_mintime'] = 'group_time' weewx.units.agg_group['historical_maxtime'] = 'group_time' class Historical(weewx.xtypes.XType): """XTypes extension to calculate historical statistics for days-of-the-year""" sql_stmts = { 'sqlite': { 'historical_min': "SELECT MIN(`min`) FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}';", 'historical_mintime': "SELECT `mintime` FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}' " "ORDER BY `min` ASC LIMIT 1;", 'historical_min_avg': "SELECT AVG(`min`) FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}';", 'historical_max': "SELECT MAX(`max`) FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}';", 'historical_maxtime': "SELECT `maxtime` FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}' " "ORDER BY `max` DESC LIMIT 1;", 'historical_max_avg': "SELECT AVG(`max`) FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}';", 'historical_avg': "SELECT SUM(`wsum`), SUM(`sumtime`) FROM {table}_day_{obs_type} " "WHERE STRFTIME('%m-%d', dateTime,'unixepoch','localtime') = '{month:02d}-{day:02d}';", }, 'mysql': { 'historical_min': "SELECT MIN(`min`) FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}';", 'historical_mintime': "SELECT `mintime` FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}' " "ORDER BY `min` ASC, dateTime ASC LIMIT 1;", 'historical_min_avg': "SELECT AVG(`min`) FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}';", 'historical_max': "SELECT MAX(`max`) FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}';", 'historical_maxtime': "SELECT `maxtime` FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}' " "ORDER BY `max` DESC, dateTime ASC LIMIT 1;", 'historical_max_avg': "SELECT AVG(`max`) FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}';", 'historical_avg': "SELECT SUM(`wsum`), SUM(`sumtime`) FROM {table}_day_{obs_type} " "WHERE FROM_UNIXTIME(dateTime, '%%m-%%d') = '{month:02d}-{day:02d}';", }, } def get_aggregate(self, obs_type, timespan, aggregate_type, db_manager, **option_dict): """Calculate historical statistical aggregation for a date in the year""" dbtype = db_manager.connection.dbtype # Do we know how to calculate this kind of aggregation? if aggregate_type not in Historical.sql_stmts[dbtype]: raise weewx.UnknownAggregation(aggregate_type) # The time span must lie on midnight-to-midnight boundaries if db_manager.first_timestamp is None or db_manager.last_timestamp is None: raise weewx.UnknownAggregation(aggregate_type) if not (isStartOfDay(timespan.start) or timespan.start == db_manager.first_timestamp) \ or not (isStartOfDay(timespan.stop) or timespan.stop == db_manager.last_timestamp): raise weewx.UnknownAggregation("%s of %s" % (aggregate_type, timespan)) start_day = datetime.date.fromtimestamp(timespan.start) stop_day = datetime.date.fromtimestamp(timespan.stop) # The timespan must cover just one day delta = stop_day - start_day if delta.days != 1: raise weewx.UnknownAggregation("%s of %s" % (aggregate_type, timespan)) interp_dict = { 'table': db_manager.table_name, 'obs_type': obs_type, 'month': start_day.month, 'day': start_day.day } # Get the correct sql statement, and format it with the interpolation dictionary. sql_stmt = Historical.sql_stmts[dbtype][aggregate_type].format(**interp_dict) try: row = db_manager.getSql(sql_stmt) except weedb.NoColumnError: raise weewx.UnknownType(aggregate_type) # Given the result set, calculate the desired value if not row or None in row: value = None elif aggregate_type == 'historical_avg': value = row[0] / row[1] if row[1] else None else: value = row[0] # Look up the unit type and group of this combination of observation type and aggregation: u, g = weewx.units.getStandardUnitType(db_manager.std_unit_system, obs_type, aggregate_type) # Form the ValueTuple and return it: return weewx.units.ValueTuple(value, u, g) class HistService(StdService): """WeeWX dummy service for initializing the Historical XTypes extension""" # Instantiate an instance of Historical, and add it to the list of xtypes weewx.xtypes.xtypes.append(Historical()) if __name__ == '__main__': import time import weewx.manager from weeutil.weeutil import TimeSpan db_manager = weewx.manager.DaySummaryManager.open({'SQLITE_ROOT': '/home/weewx/archive', 'database_name': 'big_weewx.sdb', 'driver': 'weedb.sqlite'}) # db_manager = weewx.manager.DaySummaryManager.open({'database_name': 'big_weewx', # 'driver': 'weedb.mysql', # 'host': 'localhost', # 'user': 'weewx', # 'password': 'weewx'}) start_ts = time.mktime((2019, 12, 31, 0, 0, 0, 0, 0, -1)) stop_ts = time.mktime((2020, 1, 1, 0, 0, 0, 0, 0, -1)) dh = Historical() r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_min', db_manager) print(r) r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_mintime', db_manager) print(r) r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_min_avg', db_manager) print(r) r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_max', db_manager) print(r) r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_maxtime', db_manager) print(r) r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_max_avg', db_manager) print(r) r = dh.get_aggregate('outTemp', TimeSpan(start_ts, stop_ts), 'historical_avg', db_manager) print(r)
