Claude Code for humanize: Human-Readable Python Values — Claude Skills 360 Blog
Blog / AI / Claude Code for humanize: Human-Readable Python Values
AI

Claude Code for humanize: Human-Readable Python Values

Published: February 8, 2028
Read time: 5 min read
By: Claude Skills 360

humanize formats values as human-readable text. pip install humanize. File size: import humanize; humanize.naturalsize(1_500_000) → “1.5 MB”. humanize.naturalsize(1_500_000, binary=True) → “1.4 MiB”. naturalsize(1234567890) → “1.2 GB”. Number: humanize.intcomma(1234567) → “1,234,567”. humanize.intword(1_200_000) → “1.2 million”. humanize.intword(12_000_000_000) → “12.0 billion”. humanize.apnumber(5) → “five”. humanize.apnumber(12) → “12”. humanize.ordinal(1) → “1st”. humanize.ordinal(21) → “21st”. humanize.fractional(0.333) → “1/3”. Metric: humanize.metric(1500) → “1.50 k”. humanize.metric(0.001) → “1.00 m”. Scientific: humanize.scientific(0.00123) → “1.23 x 10⁻³”. Time: humanize.naturaltime(datetime.now() - timedelta(seconds=30)) → “30 seconds ago”. humanize.naturaltime(future) → “in 2 hours”. humanize.naturalday(date.today() - timedelta(days=1)) → “yesterday”. humanize.naturaldate(date(2024,1,5)) → “January 5”. humanize.naturalday(date.today()) → “today”. Duration: humanize.precisedelta(timedelta(hours=2, minutes=15)) → “2 hours and 15 minutes”. humanize.precisedelta(timedelta(seconds=90), minimum_unit="seconds"). Locale: humanize.i18n.activate("de_DE"). humanize.intcomma(1234) → “1.234”. Deactivate: humanize.i18n.deactivate(). Claude Code generates humanize formatters, Jinja2 filters, and API response serializers.

CLAUDE.md for humanize

## humanize Stack
- Version: humanize >= 4.9 | pip install humanize
- Sizes: humanize.naturalsize(bytes) | naturalsize(bytes, binary=True) for MiB
- Numbers: intcomma(n) | intword(n) → "1.2 million" | ordinal(n) → "1st"
- Time: naturaltime(dt) → "3 minutes ago" | naturalday(d) → "yesterday"
- Duration: precisedelta(timedelta) → "2 hours and 15 minutes"
- Locale: humanize.i18n.activate("de_DE") — use with context manager
- Jinja2: register as custom filter: env.filters["naturalsize"] = humanize.naturalsize

humanize Formatting Pipeline

# app/format_utils.py — humanize formatters for API responses and templates
from __future__ import annotations

from datetime import date, datetime, timedelta, timezone
from typing import Any

import humanize


# ─────────────────────────────────────────────────────────────────────────────
# 1. File and data sizes
# ─────────────────────────────────────────────────────────────────────────────

def format_size(
    bytes: int,
    binary: bool = False,
    gnu: bool = False,
    minimum_unit: str = "Byte",
) -> str:
    """
    naturalsize(1234567) → "1.2 MB" (SI prefixes, base-10)
    naturalsize(1234567, binary=True) → "1.2 MiB" (IEC prefixes, base-2)
    naturalsize(1234567, gnu=True) → "1.2M" (single-letter, like ls -lh)
    """
    return humanize.naturalsize(bytes, binary=binary, gnu=gnu, minimum_unit=minimum_unit)


def demo_sizes() -> None:
    sizes = [512, 1_024, 10_000, 1_048_576, 1_073_741_824, 1_099_511_627_776]
    for b in sizes:
        si  = humanize.naturalsize(b)
        iec = humanize.naturalsize(b, binary=True)
        gnu = humanize.naturalsize(b, gnu=True)
        print(f"  {b:>15,}{si:>12}  {iec:>12}  {gnu:>8}")


# ─────────────────────────────────────────────────────────────────────────────
# 2. Numbers
# ─────────────────────────────────────────────────────────────────────────────

def demo_numbers() -> None:
    print("intcomma:   ", humanize.intcomma(1_234_567))          # 1,234,567
    print("intword:    ", humanize.intword(1_200_000))            # 1.2 million
    print("intword:    ", humanize.intword(42_000_000_000))       # 42.0 billion
    print("apnumber:   ", humanize.apnumber(3))                   # three
    print("apnumber:   ", humanize.apnumber(11))                  # 11
    print("ordinal 1:  ", humanize.ordinal(1))                    # 1st
    print("ordinal 2:  ", humanize.ordinal(2))                    # 2nd
    print("ordinal 21: ", humanize.ordinal(21))                   # 21st
    print("ordinal 11: ", humanize.ordinal(11))                   # 11th
    print("fractional: ", humanize.fractional(0.333))             # 1/3
    print("fractional: ", humanize.fractional(0.5))               # 1/2
    print("metric 1500:", humanize.metric(1500))                  # 1.50 k
    print("metric .001:", humanize.metric(0.001))                 # 1.00 m
    print("scientific: ", humanize.scientific(0.00123))           # 1.23 x 10⁻³
    print("clamp:      ", humanize.clamp(50, minimum=0, maximum=100))  # 50


# ─────────────────────────────────────────────────────────────────────────────
# 3. Relative time
# ─────────────────────────────────────────────────────────────────────────────

def format_relative_time(dt: datetime) -> str:
    """
    naturaltime converts a datetime to "X ago" or "in X".
    Passing a timezone-aware datetime works correctly.
    """
    return humanize.naturaltime(dt)


def demo_times() -> None:
    now = datetime.now()
    cases = [
        now - timedelta(seconds=5),
        now - timedelta(minutes=2),
        now - timedelta(hours=3),
        now - timedelta(days=1),
        now - timedelta(weeks=2),
        now + timedelta(minutes=15),
        now + timedelta(hours=2),
        now + timedelta(days=3),
    ]
    for dt in cases:
        print(f"  {str(dt - now):>20}{humanize.naturaltime(dt)}")


# ─────────────────────────────────────────────────────────────────────────────
# 4. Calendar dates
# ─────────────────────────────────────────────────────────────────────────────

def demo_dates() -> None:
    today = date.today()
    cases = [
        today,
        today - timedelta(days=1),
        today + timedelta(days=1),
        today - timedelta(days=3),
        date(2024, 1, 5),
        date(2020, 3, 15),
    ]
    for d in cases:
        print(f"  {d} → naturalday={humanize.naturalday(d):15}  naturaldate={humanize.naturaldate(d)}")


# ─────────────────────────────────────────────────────────────────────────────
# 5. Duration formatting
# ─────────────────────────────────────────────────────────────────────────────

def format_duration(td: timedelta, minimum_unit: str = "seconds") -> str:
    """
    precisedelta formats a timedelta verbosely: "2 hours, 15 minutes and 30 seconds".
    Use suppress=["seconds"] to omit small units when precision isn't needed.
    """
    return humanize.precisedelta(td, minimum_unit=minimum_unit)


def demo_durations() -> None:
    deltas = [
        timedelta(seconds=45),
        timedelta(minutes=90),
        timedelta(hours=2, minutes=15, seconds=30),
        timedelta(days=3, hours=4),
        timedelta(weeks=2, days=3),
    ]
    for td in deltas:
        short = humanize.precisedelta(td)
        long_ = humanize.precisedelta(td, suppress=[], minimum_unit="seconds")
        print(f"  {str(td):>25}{short}")


# ─────────────────────────────────────────────────────────────────────────────
# 6. API response serializer
# ─────────────────────────────────────────────────────────────────────────────

def humanize_record(record: dict) -> dict:
    """
    Transform a raw database record into a display-ready dict with
    human-readable values alongside the raw values.
    """
    result = dict(record)

    # Bytes → readable size
    if "file_size" in record and isinstance(record["file_size"], int):
        result["file_size_human"] = humanize.naturalsize(record["file_size"])

    # Datetime → relative time
    if "created_at" in record and isinstance(record["created_at"], datetime):
        result["created_at_human"] = humanize.naturaltime(record["created_at"])
        result["created_at_date"]  = humanize.naturaldate(record["created_at"].date())

    # Large counts
    if "download_count" in record and isinstance(record["download_count"], int):
        result["download_count_human"] = humanize.intcomma(record["download_count"])
        if record["download_count"] >= 1_000_000:
            result["download_count_word"] = humanize.intword(record["download_count"])

    # Order number with ordinal
    if "rank" in record and isinstance(record["rank"], int):
        result["rank_ordinal"] = humanize.ordinal(record["rank"])

    return result


# ─────────────────────────────────────────────────────────────────────────────
# 7. Jinja2 template filters
# ─────────────────────────────────────────────────────────────────────────────

def register_humanize_filters(env) -> None:
    """
    Register humanize functions as Jinja2 template filters.
    Usage in templates: {{ file.size | naturalsize }}
                        {{ post.created_at | naturaltime }}
                        {{ user.rank | ordinal }}
    """
    env.filters["naturalsize"]  = humanize.naturalsize
    env.filters["naturaltime"]  = humanize.naturaltime
    env.filters["naturalday"]   = humanize.naturalday
    env.filters["naturaldate"]  = humanize.naturaldate
    env.filters["precisedelta"] = humanize.precisedelta
    env.filters["intcomma"]     = humanize.intcomma
    env.filters["intword"]      = humanize.intword
    env.filters["ordinal"]      = humanize.ordinal
    env.filters["apnumber"]     = humanize.apnumber


# ─────────────────────────────────────────────────────────────────────────────
# 8. Locale-aware formatting
# ─────────────────────────────────────────────────────────────────────────────

def demo_locales() -> None:
    """
    humanize.i18n.activate changes the locale for number/date formatting.
    Always deactivate after use (or use a context manager).
    """
    from contextlib import contextmanager

    @contextmanager
    def locale(lang: str):
        humanize.i18n.activate(lang)
        try:
            yield
        finally:
            humanize.i18n.deactivate()

    for lang in ["en_US", "de_DE", "ru_RU", "fr_FR"]:
        try:
            with locale(lang):
                print(f"  [{lang}] intcomma(1234567)={humanize.intcomma(1_234_567)}  "
                      f"naturalday(yesterday)={humanize.naturalday(date.today() - timedelta(days=1))}")
        except Exception as e:
            print(f"  [{lang}] locale not available: {e}")


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== Sizes ===")
    demo_sizes()

    print("\n=== Numbers ===")
    demo_numbers()

    print("\n=== Relative times ===")
    demo_times()

    print("\n=== Calendar dates ===")
    demo_dates()

    print("\n=== Durations ===")
    demo_durations()

    print("\n=== Record serializer ===")
    record = {
        "name": "data.csv",
        "file_size": 15_728_640,
        "created_at": datetime.now() - timedelta(hours=3),
        "download_count": 1_234_567,
        "rank": 3,
    }
    human = humanize_record(record)
    for k, v in sorted(human.items()):
        print(f"  {k:30}: {v}")

    print("\n=== Locales ===")
    demo_locales()

For the f"{value:,.0f}" format string alternative — Python’s f"{bytes:,}" adds commas to integers but doesn’t know whether 1_048_576 is “1 MB” or “1 MiB”, f"{dt:%Y-%m-%d %H:%M}" outputs absolute timestamps but not “3 minutes ago”, and format strings produce no ordinal suffix or AP-style number words, while humanize.naturalsize() picks the right SI or IEC unit automatically, humanize.naturaltime() returns “3 minutes ago” or “in 2 hours” relative to now, and humanize.ordinal(3) returns “3rd” — the presentation library that removes all the edge-case logic from your template or serializer code. For the arrow / pendulum alternative — arrow and pendulum are datetime manipulation libraries that create timezone-aware datetime objects and expose .humanize() as a chainable method, requiring the data to be stored as arrow/pendulum objects, while humanize works on standard datetime.datetime and datetime.timedelta objects and adds naturaltime() / precisedelta() as standalone formatting functions that accept any Python datetime. The Claude Skills 360 bundle includes humanize skill sets covering naturalsize with SI and binary modes, intcomma/intword/apnumber/ordinal/fractional, naturaltime for relative timestamps, naturalday/naturaldate for calendar display, precisedelta for verbose duration strings, metric and scientific notation, humanize_record for API response enrichment, Jinja2 filter registration, locale activation with i18n.activate, and Django template tag integration. Start with the free tier to try human-readable formatting code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free