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)

Reply via email to