Skip to content

Commit

Permalink
Merge pull request #1083 from akrherz/250127
Browse files Browse the repository at this point in the history
📝 Sundry review and datetime lint
  • Loading branch information
akrherz authored Jan 27, 2025
2 parents 2da5cd9 + 32aa03b commit 6861363
Show file tree
Hide file tree
Showing 40 changed files with 190 additions and 155 deletions.
49 changes: 30 additions & 19 deletions pylib/iemweb/autoplot/scripts/p51.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from pyiem.database import get_sqlalchemy_conn
from pyiem.exceptions import NoDataFound
from pyiem.plot import figure
from sqlalchemy import text

PDICT = {
"all": "Show All Three Plots",
Expand Down Expand Up @@ -124,14 +125,18 @@ def plotter(ctx: dict):
climosite = ctx["_nt"].sts[station]["climate_site"]
with get_sqlalchemy_conn("coop") as conn:
climo = pd.read_sql(
f"""
SELECT day, sday, gddxx(%s, %s, high, low) as {glabel},
text(f"""
SELECT day, sday, gddxx(:gddbase, :gddceil, high, low) as {glabel},
sdd86(high, low) as sdd86, precip
from alldata WHERE station = %s and
from alldata WHERE station = :station and
year >= 1951 ORDER by day ASC
""",
"""),
conn,
params=(gddbase, gddceil, ctx["_nt"].sts[station]["climate_site"]),
params={
"gddbase": gddbase,
"gddceil": gddceil,
"station": ctx["_nt"].sts[station]["climate_site"],
},
index_col="day",
)
if climo.empty:
Expand Down Expand Up @@ -182,32 +187,38 @@ def plotter(ctx: dict):
climo = pd.DataFrame(rows)

# build the obs
with get_sqlalchemy_conn("iem") as conn:
with get_sqlalchemy_conn("isuag") as conn:
df = pd.read_sql(
f"""SELECT day, to_char(day, 'mmdd') as sday,
gddxx(%s, %s, max_tmpf, min_tmpf) as o{glabel},
coalesce(pday, 0) as oprecip,
sdd86(max_tmpf, min_tmpf) as osdd86 from summary s JOIN stations t
ON (s.iemid = t.iemid)
WHERE t.id = %s and t.network = %s and
to_char(day, 'mmdd') != '0229' ORDER by day ASC""",
text(f"""
SELECT valid as day, to_char(valid, 'mmdd') as sday,
gddxx(:gddbase, :gddceil, c2f(tair_c_max_qc), c2f(tair_c_min_qc))
as o{glabel},
coalesce(rain_in_tot_qc, 0) as oprecip,
sdd86( c2f(tair_c_max_qc), c2f(tair_c_min_qc)) as osdd86
from sm_daily
WHERE station = :station and to_char(valid, 'mmdd') != '0229'
ORDER by day ASC"""),
conn,
params=(gddbase, gddceil, station, ctx["network"]),
params={
"gddbase": gddbase,
"gddceil": gddceil,
"station": station,
},
index_col=None,
)
# Now we need to join the frames
df = pd.merge(df, climo, on="sday")
df = df.sort_values("day", ascending=True)
df = df.set_index("day")
df["precip_diff"] = df["oprecip"] - df["cprecip"]
df[glabel + "_diff"] = df["o" + glabel] - df["c" + glabel]
df[f"{glabel}_diff"] = df[f"o{glabel}"] - df[f"c{glabel}"]

ab = ctx["_nt"].sts[station]["archive_begin"]
if ab is None:
raise NoDataFound("Unknown station metadata.")
fig = figure(apctx=ctx)
if whichplots == "all":
ax1 = fig.add_axes([0.1, 0.7, 0.8, 0.2])
ax1 = fig.add_axes((0.1, 0.7, 0.8, 0.2))
ax2 = fig.add_axes(
[0.1, 0.6, 0.8, 0.1], sharex=ax1, facecolor="#EEEEEE"
)
Expand All @@ -218,17 +229,17 @@ def plotter(ctx: dict):
"SDD(base=86)"
)
elif whichplots == "gdd":
ax1 = fig.add_axes([0.14, 0.31, 0.8, 0.57])
ax1 = fig.add_axes((0.14, 0.31, 0.8, 0.57))
ax2 = fig.add_axes(
[0.14, 0.11, 0.8, 0.2], sharex=ax1, facecolor="#EEEEEE"
)
title = f"GDD(base={gddbase:.0f},ceil={gddceil:.0f})"
elif whichplots == "precip":
ax3 = fig.add_axes([0.1, 0.11, 0.8, 0.75])
ax3 = fig.add_axes((0.1, 0.11, 0.8, 0.75))
ax1 = ax3
title = "Precipitation"
else: # sdd
ax4 = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax4 = fig.add_axes((0.1, 0.1, 0.8, 0.8))
ax1 = ax4
title = "Stress Degree Days (base=86)"

Expand Down
10 changes: 8 additions & 2 deletions pylib/iemweb/request/daily.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
""".. title:: IEM Computed Daily Summaries
Return to `API Services </api/#cgi>`_
Documentation for /cgi-bin/request/daily.py
-------------------------------------------
Expand All @@ -14,13 +16,17 @@
Request all high temperature data for Ames, IA (AMW) for the month of January
2019:
https://mesonet.agron.iastate.edu/cgi-bin/request/daily.py?sts=2019-01-01&ets=2019-01-31&network=IA_ASOS&stations=AMW&var=max_temp_f&format=csv
https://mesonet.agron.iastate.edu/cgi-bin/request/daily.py?\
sts=2019-01-01&ets=2019-01-31&network=IA_ASOS&stations=AMW&\
var=max_temp_f&format=csv
Request daily precipitation and the climatology for all stations in Washington
state on 23 June 2023 in Excel format:
https://mesonet.agron.iastate.edu/cgi-bin/request/daily.py?sts=2023-06-23&ets=2023-06-23&network=WA_ASOS&stations=_ALL&var=precip_in,climo_precip_in&format=excel
https://mesonet.agron.iastate.edu/cgi-bin/request/daily.py?\
sts=2023-06-23&ets=2023-06-23&network=WA_ASOS&stations=_ALL&\
var=precip_in,climo_precip_in&format=excel
"""

Expand Down
4 changes: 2 additions & 2 deletions pylib/iemweb/request/gis/lsr.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"""

import datetime
import zipfile
from datetime import timedelta
from io import BytesIO, StringIO

import fiona
Expand Down Expand Up @@ -196,7 +196,7 @@ def get_time_domain(form):
if form["recent"] is not None:
# Allow for specifying a recent number of seconds
ets = utc()
sts = ets - datetime.timedelta(seconds=form["recent"])
sts = ets - timedelta(seconds=form["recent"])
return sts, ets
if form["sts"] is None:
raise IncompleteWebRequest("GET start time parameters missing")
Expand Down
4 changes: 2 additions & 2 deletions pylib/iemweb/request/gis/nexrad_storm_attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
"""

import datetime
import zipfile
from datetime import timedelta
from io import BytesIO, StringIO

import shapefile
Expand Down Expand Up @@ -94,7 +94,7 @@ def run(environ, start_response):
len(environ["radar"]) > 2
and (environ["ets"] - environ["sts"]).days > 6
):
environ["ets"] = environ["sts"] + datetime.timedelta(days=7)
environ["ets"] = environ["sts"] + timedelta(days=7)
fn = f"stormattr_{environ['sts']:%Y%m%d%H%M}_{environ['ets']:%Y%m%d%H%M}"

with get_sqlalchemy_conn("radar") as conn:
Expand Down
6 changes: 4 additions & 2 deletions pylib/iemweb/request/gis/pireps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
""".. title:: Pilot Weather Report (PIREP) Data Service
Return to `API Services </api/#cgi>`_
Documentation for /cgi-bin/request/gis/pireps.py
------------------------------------------------
Expand Down Expand Up @@ -30,8 +32,8 @@
"""

import datetime
import zipfile
from datetime import timedelta
from io import BytesIO, StringIO

import shapefile
Expand Down Expand Up @@ -140,7 +142,7 @@ def run(environ, start_response):
)
else:
if (environ["ets"] - environ["sts"]).days > 120:
environ["ets"] = environ["sts"] + datetime.timedelta(days=120)
environ["ets"] = environ["sts"] + timedelta(days=120)
sql = f"""
SELECT to_char(valid at time zone 'UTC', 'YYYYMMDDHH24MI') as utctime,
case when is_urgent then 'T' else 'F' end,
Expand Down
12 changes: 7 additions & 5 deletions pylib/iemweb/request/grx/time_mot_loc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
""".. title:: NWS TOR+SVR Warning Time-Mot-Loc
Return to `API Services </api/#cgi>`_
Changelog
---------
Expand All @@ -15,9 +17,9 @@
"""

import datetime
import math
import re
from datetime import timedelta
from io import StringIO
from zoneinfo import ZoneInfo

Expand Down Expand Up @@ -89,7 +91,7 @@ def gentext(sio, row, grversion):
lons.append(float(token[0]))
lats.append(float(token[1]))
for seconds in [0, duration / 2.0, duration]:
valid = tml_valid + datetime.timedelta(seconds=seconds)
valid = tml_valid + timedelta(seconds=seconds)
ts = valid.strftime("%H%Mz")
sio.write(
f"Color: 255 255 0\n{time_range}"
Expand All @@ -107,7 +109,7 @@ def gentext(sio, row, grversion):
sio.write("Color: 255 255 255\nThreshold:10\n\n")
for lon, lat in zip(lons, lats):
for minute in range(int(duration / 60.0) + 1):
valid = tml_valid + datetime.timedelta(minutes=minute)
valid = tml_valid + timedelta(minutes=minute)
ts = valid.strftime("%H%Mz")
lon2, lat2 = extrapolate(lon, lat, smps * minute * 60, drct)
sio.write(f"Place: {lat2:.4f},{lon2:.4f},{ts}\n")
Expand All @@ -131,8 +133,8 @@ def application(environ, start_response):
tmlabel = valid.strftime("%H%Mz")
if grversion >= 1.5 or environ["valid"]:
# Pull larger window of data to support TimeRange
t1 = valid - datetime.timedelta(hours=2)
t2 = valid + datetime.timedelta(hours=2)
t1 = valid - timedelta(hours=2)
t2 = valid + timedelta(hours=2)
tmlabel = valid.strftime("%b %d %Y %H%Mz")
cursor.execute(
f"""SELECT ST_x(tml_geom) as lon, ST_y(tml_geom) as lat,
Expand Down
36 changes: 16 additions & 20 deletions pylib/iemweb/request/maxcsv.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@
"""

import datetime
import re
from datetime import date, timedelta, timezone
from zoneinfo import ZoneInfo

# third party
Expand Down Expand Up @@ -127,8 +127,8 @@ def figure_phase(p1: float, p2: float) -> str:

def do_monthly_summary(station, year, month):
"""Compute some requested monthly summary stats."""
sts = datetime.date(year, month, 1)
ets = (sts + datetime.timedelta(days=35)).replace(day=1)
sts = date(year, month, 1)
ets = (sts + timedelta(days=35)).replace(day=1)
with get_sqlalchemy_conn("iem") as conn:
df = pd.read_sql(
text(
Expand Down Expand Up @@ -182,16 +182,16 @@ def do_moonphase(lon, lat):
{
"new_moon": ephem.next_new_moon(utc())
.datetime()
.replace(tzinfo=datetime.timezone.utc),
.replace(tzinfo=timezone.utc),
"full_moon": ephem.next_full_moon(utc())
.datetime()
.replace(tzinfo=datetime.timezone.utc),
.replace(tzinfo=timezone.utc),
"first_quarter": ephem.next_first_quarter_moon(utc())
.datetime()
.replace(tzinfo=datetime.timezone.utc),
.replace(tzinfo=timezone.utc),
"last_quarter": ephem.next_last_quarter_moon(utc())
.datetime()
.replace(tzinfo=datetime.timezone.utc),
.replace(tzinfo=timezone.utc),
}
).sort_values(ascending=True)
# Figure out the timezone
Expand Down Expand Up @@ -237,20 +237,16 @@ def do_moon(lon, lat):
obs.lat = str(lat)
obs.long = str(lon)
obs.date = utc().strftime("%Y/%m/%d %H:%M")
r1 = obs.next_rising(moon).datetime().replace(tzinfo=datetime.timezone.utc)
r1 = obs.next_rising(moon).datetime().replace(tzinfo=timezone.utc)
p1 = moon.moon_phase
obs.date = r1.strftime("%Y/%m/%d %H:%M")
s1 = (
obs.next_setting(moon).datetime().replace(tzinfo=datetime.timezone.utc)
)
s1 = obs.next_setting(moon).datetime().replace(tzinfo=timezone.utc)
# Figure out the next rise time
obs.date = s1.strftime("%Y/%m/%d %H:%M")
r2 = obs.next_rising(moon).datetime().replace(tzinfo=datetime.timezone.utc)
r2 = obs.next_rising(moon).datetime().replace(tzinfo=timezone.utc)
p2 = moon.moon_phase
obs.date = r2.strftime("%Y/%m/%d %H:%M")
s2 = (
obs.next_setting(moon).datetime().replace(tzinfo=datetime.timezone.utc)
)
s2 = obs.next_setting(moon).datetime().replace(tzinfo=timezone.utc)
label = figure_phase(p1, p2)
# Figure out the timezone
pgconn, cursor = get_dbconnc("mesosite")
Expand Down Expand Up @@ -339,7 +335,7 @@ def do_webcams(network):
return df


def do_iowa_azos(date, itoday=False):
def do_iowa_azos(dt: date, itoday=False):
"""Dump high and lows for Iowa ASOS"""
with get_sqlalchemy_conn("iem") as conn:
df = pd.read_sql(
Expand All @@ -349,12 +345,12 @@ def do_iowa_azos(date, itoday=False):
st_y(geom) as latitude,
st_x(geom) as longitude, s.day, s.max_tmpf::int as high,
s.min_tmpf::int as low, coalesce(pday, 0) as precip
from stations n JOIN summary_{date.year} s on (n.iemid = s.iemid)
from stations n JOIN summary_{dt.year} s on (n.iemid = s.iemid)
WHERE n.network = 'IA_ASOS' and s.day = :dt
"""
),
conn,
params={"dt": date},
params={"dt": dt},
index_col="locationid",
)
if itoday:
Expand Down Expand Up @@ -798,9 +794,9 @@ def router(appname):
elif appname == "iarwis":
df = do_iarwis()
elif appname == "iowayesterday":
df = do_iowa_azos(datetime.date.today() - datetime.timedelta(days=1))
df = do_iowa_azos(date.today() - timedelta(days=1))
elif appname == "iowatoday":
df = do_iowa_azos(datetime.date.today(), True)
df = do_iowa_azos(date.today(), True)
elif appname == "kcrgcitycam":
df = do_webcams("KCRG")
elif appname == "uvi":
Expand Down
7 changes: 4 additions & 3 deletions scripts/GIS/attribute2shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
Run every minute from RUN_1MIN.sh
"""

import datetime
import os
import subprocess
import zipfile
from datetime import timedelta

import shapefile
from pyiem.util import get_dbconnc, logger, utc
from pyiem.database import get_dbconnc
from pyiem.util import logger, utc

LOG = logger()
INFORMATION = """
Expand Down Expand Up @@ -100,7 +101,7 @@ def main():

# Delete anything older than 20 minutes
now = utc()
ets = now - datetime.timedelta(minutes=20)
ets = now - timedelta(minutes=20)

shp = shpschema()

Expand Down
Loading

0 comments on commit 6861363

Please sign in to comment.