49 lines
1.4 KiB
Python
49 lines
1.4 KiB
Python
"""Number / unit / date formatters so every document writes values the same way.
|
||||
|
|
See MPM_Document_Standard.md §5 (Units and numbers)."""
|
|||
|
|
import datetime as _dt
|
|||
|
|
from fractions import Fraction
|
|||
|
|
|
|||
|
|
|
|||
|
|
def ftin(x):
|
|||
|
|
"""Inches -> feet-inches to the nearest 1/16: 154 -> 12'-10", 153.5 -> 12'-9 1/2"."""
|
|||
|
|
x = round(x * 16) / 16
|
|||
|
|
ft = int(x // 12)
|
|||
|
|
rem = x - ft * 12
|
|||
|
|
whole = int(rem)
|
|||
|
|
frac = Fraction(rem - whole).limit_denominator(16)
|
|||
|
|
f = f" {frac.numerator}/{frac.denominator}" if frac else ""
|
|||
|
|
return f"{ft}'-{whole}{f}\""
|
|||
|
|
|
|||
|
|
|
|||
|
|
def inch(x):
|
|||
|
|
"""Inches to the nearest 1/16: 7.25 -> 7 1/4"."""
|
|||
|
|
x = round(x * 16) / 16
|
|||
|
|
whole = int(x)
|
|||
|
|
frac = Fraction(x - whole).limit_denominator(16)
|
|||
|
|
if frac and whole:
|
|||
|
|
return f"{whole} {frac.numerator}/{frac.denominator}\""
|
|||
|
|
if frac:
|
|||
|
|
return f"{frac.numerator}/{frac.denominator}\""
|
|||
|
|
return f"{whole}\""
|
|||
|
|
|
|||
|
|
|
|||
|
|
def mm_in(mm, digits=2):
|
|||
|
|
"""'1448 mm (57.01 in.)' — metric primary with inch conversion."""
|
|||
|
|
return f"{mm:g} mm ({mm / 25.4:.{digits}f} in.)"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def signed(s, value):
|
|||
|
|
"""Prefix a true minus sign or plus: signed('13\"', -1) -> '−13\"'."""
|
|||
|
|
return ("−" if value < 0 else "+" if value > 0 else "") + s
|
|||
|
|
|
|||
|
|
|
|||
|
|
def parse_date(d):
|
|||
|
|
if isinstance(d, _dt.date):
|
|||
|
|
return d
|
|||
|
|
return _dt.date.fromisoformat(d)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def show_date(d):
|
|||
|
|
"""Display format used on every page: 'Nov 5, 2026'."""
|
|||
|
|
d = parse_date(d)
|
|||
|
|
return f"{d:%b} {d.day}, {d.year}"
|