Files
sqlgen/docs/timestamp_operations.md
Dr. Patrick Urbanke (劉自成) f95156df77 Added operations on time stamps (#24)
2025-07-02 20:04:50 +02:00

4.0 KiB

Timestamp and Date/Time Functions

The sqlgen library provides a comprehensive set of operations for working with timestamps, dates, and times. These functions allow you to extract date/time parts, perform arithmetic, and convert between types in a type-safe and composable way. All timestamp operations work with the sqlgen::Timestamp<...> type (including the provided aliases Date and DateTime).

Timestamp Types

  • Timestamp<format>: Represents a timestamp with a custom format (see sqlgen::Timestamp).
  • Date: Alias for Timestamp<"%Y-%m-%d"> (date only).
  • DateTime: Alias for Timestamp<"%Y-%m-%d %H:%M:%S"> (date and time).

Date/Time Extraction Functions

These functions extract parts of a timestamp or date:

  • year(ts): Extracts the year as an integer.
  • month(ts): Extracts the month (1-12).
  • day(ts): Extracts the day of the month (1-31).
  • hour(ts): Extracts the hour (0-23).
  • minute(ts): Extracts the minute (0-59).
  • second(ts): Extracts the second (0-59).
  • weekday(ts): Extracts the day of the week (0 = Sunday for SQLite, 0 = Monday for Postgres).
year("birthday"_c) | as<"year">
month("birthday"_c) | as<"month">
day("birthday"_c) | as<"day">
hour("birthday"_c) | as<"hour">
minute("birthday"_c) | as<"minute">
second("birthday"_c) | as<"second">
weekday("birthday"_c) | as<"weekday">

Timestamp Arithmetic

You can add or subtract durations (e.g., days, years, weeks, milliseconds) to/from timestamp columns using standard C++ chrono types:

("birthday"_c + std::chrono::days(10)) | as<"birthday_plus_10">
("birthday"_c + std::chrono::years(1) - std::chrono::weeks(2)) | as<"birthday_shifted">

This is translated to the appropriate SQL for the backend (e.g., datetime(..., '+10 days') for SQLite, + INTERVAL '10 days' for Postgres).


Days Between

Calculates the number of days between two timestamps or dates:

days_between("birthday"_c, Date("2011-01-01")) | as<"age_in_days">

Unix Epoch Conversion

Converts a timestamp to the number of seconds since the Unix epoch:

unixepoch("birthday"_c) | as<"birthday_unixepoch">
unixepoch("birthday"_c + std::chrono::days(10)) | as<"birthday_unixepoch_plus_10">

Timestamp Construction and Conversion

You can construct or cast timestamps from strings or from extracted parts:

cast<Date>(concat(cast<std::string>(year("birthday"_c)), "-", cast<std::string>(month("birthday"_c)), "-", cast<std::string>(day("birthday"_c)))) | as<"birthday_recreated">

Example: Working with Timestamps

struct Birthday {
    Date birthday;
    Date birthday_recreated;
    time_t birthday_unixepoch;
    double age_in_days;
    int hour;
    int minute;
    int second;
    int weekday;
};

const auto get_birthdays = select_from<Person>(
    ("birthday"_c + std::chrono::days(10)) | as<"birthday">,
    (cast<Date>(concat(cast<std::string>(year("birthday"_c)), "-",
                        cast<std::string>(month("birthday"_c)), "-",
                        cast<std::string>(day("birthday"_c))))) | as<"birthday_recreated">,
    days_between("birthday"_c, Date("2011-01-01")) | as<"age_in_days">,
    unixepoch("birthday"_c + std::chrono::days(10)) | as<"birthday_unixepoch">,
    hour("birthday"_c) | as<"hour">,
    minute("birthday"_c) | as<"minute">,
    second("birthday"_c) | as<"second">,
    weekday("birthday"_c) | as<"weekday">
) | order_by("id"_c) | to<std::vector<Birthday>>;

This generates SQL like:

SQLite:

SELECT datetime("birthday", '+10 days') AS "birthday", ...

Postgres:

SELECT "birthday" + INTERVAL '10 days' AS "birthday", ...

Notes

  • All timestamp operations are type-safe and propagate nullability as described above.
  • You can chain and nest timestamp operations with other operations.
  • Duration arithmetic supports std::chrono::days, std::chrono::years, std::chrono::weeks, std::chrono::milliseconds, etc.
  • The result types and SQL translation may differ slightly between SQLite and Postgres, but the C++ interface is unified.