Values, units and types

weewx-skyfield manual · weewx-skyfield on GitHub · Report an issue


Most almanac questions are answered by the tag index. This page answers the one it can’t: what kind of thing comes back, and why the same angle is available in three different forms. If a number on your page is off by a factor of 3600, or 57.3, or reads N/A when you expected a value, the answer is here.

Three families

Family Example What it is
Plain float, decimal degrees $almanac.mars.alt A bare Python float. No units attached, no formatting.
PyEphem-shaped, radians $almanac.moon.colong A bare float in radians, matching PyEphem’s numeric scale — which also carries .degrees and .radians.
ValueHelper $almanac.mars.altitude WeeWX’s unit-aware value: formats itself, converts on ask, renders N/A when there is no answer.

The split is not arbitrary. Tags that PyEphem also served keep PyEphem’s scale, so a template ported from the built-in almanac keeps working — including the familiar math.degrees($almanac.moon.colong) idiom. Tags with no PyEphem counterpart are ValueHelpers, because that is what a modern WeeWX skin wants. And where both are useful, you get both: a plain float and a unit-aware twin.

The twins

Every plain-float angle has a ValueHelper sibling carrying the same answer:

Plain float (degrees) Unit-aware twin Twin’s group
az azimuth degree_compass
alt altitude group_angle
ra topo_ra degree_compass
dec topo_dec group_angle
a_ra / a_dec astro_ra / astro_dec degree_compass / group_angle
g_ra / g_dec geo_ra / geo_dec degree_compass / group_angle
ha hour_angle group_angle
hlong / hlat hlongitude / hlatitude degree_compass / group_angle
elong elongation group_angle
sidereal_time sidereal_angle degree_compass
solar_time solar_angle degree_compass
phase illumination group_percent
earth_distance distance group_distance_astronomical
sun_distance distance_from_sun group_distance_astronomical
radius radius_size group_angle

Two consequences worth knowing. A degree_compass twin gives you .ordinal_compass for free, so $almanac.iss.next_pass.rise_azimuth.ordinal_compass renders WSW. And a group_angle ValueHelper carries its angle in radians internally, converting to whatever the report displays — so never read .raw from one expecting degrees.

mag deliberately has no twin: a magnitude is unitless, with nothing to convert or label.

The .raw trap

This one has bitten a real page, and it is the single most important paragraph here.

ValueHelper.raw gives you the value unformatted — it does not give it to you unconverted. A .raw read follows the report’s own converter. So if a report (or a skin, or a [[Defaults]] block) sets

[Units]
    [[Groups]]
        group_deltatime = hour

then $almanac.sun.visible.raw returns hours, not seconds — and a template doing seconds arithmetic on it silently produces numbers that are 3600× too small. That is issue #2: a page’s “visible” figures all read zero, with nothing in any log to say why.

Pin the unit at every .raw read. Write $almanac.sun.visible.second.raw, not $almanac.sun.visible.raw; write $almanac.sunrise.unix_epoch.raw, not $almanac.sunrise.raw. The pinned spelling means the same thing on every station, whatever its unit settings.

The same applies to weewx-loopdata almanac fields: almanac.sun.visible.second.raw and almanac.sunrise.unix_epoch.raw are the spellings that cannot change meaning under you. See Live-updating pages.

The astronomical unit

distance and distance_from_sun report in group_distance_astronomical, a group this extension registers with WeeWX. Its display unit is the astronomical unit in every unit system — US, metric or metricwx — because interplanetary distances read naturally in AU and absurdly in ten-digit kilometers. The default rendering is 1.8588 AU.

Converting is per-tag and needs no configuration: $almanac.moon.distance.km, $almanac.mars.distance.mile. Restyling the whole family is a units override.

A satellite’s .distance is the exception, and deliberately so: it is the slant range from you to the satellite, in ordinary group_distance, because nobody measures an overhead pass in AU.

How far away a time can be

A time ValueHelper renders itself through one of WeeWX’s [Units] [[TimeFormats]] entries, chosen by the context the tag was built with. Two contexts matter here, and the rule is simply how far from now the instant can be:

Context Default format Renders Used for
ephem_day %X 03:11:25 AM Instants at most about a day away: $almanac.sunrise, a body’s rise, set and transit, the next_rising family.
ephem_year %x %X 06/22/2025 03:11:25 AM Instants days, months or years out: equinoxes and solstices, the moon-phase finders, the moon’s and Earth’s apsides, next_supermoon, eclipses, meteor-shower peaks, a comet’s perihelion, the elements_epoch of a satellite or comet — and everything about a satellite pass.

ephem_day does not promise the almanac’s own date. A body’s rise, set and transit mean the event occurring on the almanac’s day, searched forward from local midnight, so one can land just past midnight and carry the next day’s date while still rendering as a bare clock time: at Palo Alto on 15 June 2025, $almanac.moon.rise is 00:08 the following morning. WeeWX’s built-in almanac computes and formats these the same way, and this extension matches it deliberately — a template ported from PyEphem keeps rendering what it always rendered. (One difference worth knowing: in the built-in almanac $almanac.sunrise is a separate calendar-day computation, while here it is exactly $almanac.sun.rise.)

Satellite times are ephem_year because passes are searched across the orbital elements’ seven-day validity window, so $almanac.iss.next_visible_pass.rise routinely names an instant one to seven days out. A bare clock time for a pass three days away does not merely lose the date — it reads as tonight. That covers the three pass attributes rise, culmination and set, and the satellite’s own rise, transit and set, which come off the same pass list.

To change one tag only — a pass time you want as a bare clock time, say — format it in place: $almanac.iss.next_pass.rise.format(format_string="%X").

To restyle a whole family, override its context in your skin:

[Units]
    [[TimeFormats]]
        ephem_year = %b %d %H:%M

That reaches every ephem_year tag in the table above, not only the satellite times: the equinoxes, the moon’s phases and apsides, eclipses, meteor-shower peaks and a comet’s perihelion change with them.

Radians that know they are radians

The PyEphem-shaped tags — libration_lat, libration_long, colong, subsolar_lat, cmlI, cmlII, earth_tilt, sun_tilt, parallactic_angle, and $almanac.separation() — return a float subclass that behaves exactly like the float PyEphem returned, so existing templates are unaffected, but also answers:

$almanac.moon.parallactic_angle           ## the value, in radians
$almanac.moon.parallactic_angle.degrees   ## the same angle in decimal degrees
$almanac.moon.parallactic_angle.radians   ## names the value itself

parallactic_angle has one extra wrinkle: PyEphem served it as a method, so $almanac.moon.parallactic_angle() — with the parentheses — still works. The value is callable as well as readable.

Attributes, methods, and why it matters

Almost everything this almanac serves is a plain attribute. That is a deliberate contract, not an accident: Cheetah calls a method for you automatically, but weewx-loopdata walks attribute chains with plain getattr, which does not. A tag served as a method would work in a template and silently fail as a live field.

So pass attributes (next_pass.rise, .max_altitude, .duration), shower attributes, and constellation.abbr are all plain attributes.

The exceptions, which you must call:

Callable Why
$almanac.sun.visible_change() Takes an argument: visible_change(2) compares against two days ago.
$almanac.separation(a, b) Takes two bodies.
$almanac(...) The almanac itself, to time-travel or set a horizon.
$almanac.sun(use_center=1) A body, to measure to its center.

When there is no answer

The almanac never invents a number and never breaks a report to admit it:

  • A ValueHelper with no value renders N/A. A body that never rises, a satellite with no pass this week, a comet the MPC has dropped, a star with no measured parallax — all report an empty ValueHelper, and .raw is None.
  • A plain-value tag reports None in the same situations — sunlit, visible on a pass.
  • A tag outside a surface reports a per-tag error, which WeeWX renders in place without taking down the page. Asking a satellite for .phase, or Mars for .next_pass, lands here.
  • A time outside the ephemeris (before mid-1899 or after 2053) falls through to PyEphem if installed, and otherwise reports a per-tag error.

The distinction that matters: N/A means the question was valid and the answer is genuinely unknown or nonexistent. It is never a stale value and never a silent zero.

Diagnosing a wrong number

Symptom Almost certainly
Value 3600× or 60× out A .raw read on a duration under a group_deltatime override — pin the unit.
Value 57.3× out Mixing a radians tag with a degrees tag. Check the tag index Type column.
Angle displays as a compass point when you wanted a number You read a degree_compass twin; use the plain float, or .raw with a pinned unit.
N/A everywhere for one body Its elements are missing or stale — check elements_epoch and elements_age, and see Troubleshooting.
A satellite time now shows a date Satellite times print in ephem_year as of 2.5. For a bare clock time, format that tag with .format(format_string="%X") rather than overriding ephem_year — see How far away a time can be.
Time is right but the date is a day off A day-window verb (rise, set, transit) answers for the almanac’s day; you may want next_rising.

weewx-skyfield is Copyright © 2022–2026 John A Kline and is licensed under the GNU Public License v3.