#pdflite/date

    moonbitlang/pdflite/date parses and writes PDF date strings. It keeps date fields as integers so callers can inspect malformed or boundary data through PdfError instead of relying on host time-zone behavior.

    flowchart LR String["D:YYYYMMDDHHmmSSOHH'mm'"] --> Parser[pdf_date_of_string] Bytes[PDF bytes] --> Parser Parser --> PdfDate PdfDate --> Writer[pdf_string_of_date] Writer --> Out[PDF date string]

    #Checked Examples

    ///|
    test "date strings round trip" {
    let input = "D:20240515112233+08'00'"
    let date = try! @date.pdf_date_of_string(input)
    inspect(try! @date.pdf_string_of_date(date), content=input)
    }

    ///|
    test "bad date syntax raises shared PdfError" {
    let result : Result[@date.PdfDate, Error] = try
    @date.pdf_date_of_string("not a date")
    catch {
    err => Err(err)
    } noraise {
    value => Ok(value)
    }
    guard result is Err(@core.PdfError::BadDate) else {
    fail("expected BadDate for malformed PDF date text")
    }
    }

    #Package Notes

    • The parser accepts the PDF date grammar used by document metadata.
    • pdf_date_of_bytes, pdf_date_of_view, and pdf_date_of_string share the same validation path.
    • Writers return PDF bytes or strings so higher packages can store dates in objects without implicit Unicode conversion.

    #Pedantic Boundaries

    • This package owns PDF date syntax, not calendar arithmetic or host time-zone conversion.
    • PdfDate stores numeric fields exactly as parsed or constructed. Callers are responsible for choosing meaningful dates before writing metadata.
    • Malformed date text should raise PdfError::BadDate; tests should not accept ambiguous fallback dates.
    • Byte-based entry points are the canonical boundary for PDF objects. String entry points are convenience wrappers for already-decoded ASCII-compatible date text.

    #Verification Notes

    • README examples are blackbox tests for the public date API.
    • Add tests for both round trips and malformed input when changing parser rules.
    • Run moon test date/README.mbt.md after editing this file.
    • Run moon info before review; this README should not change date/pkg.generated.mbti.

    PdfDate

    pub(all) struct PdfDate {
    year : Int
    month : Int
    day : Int
    hour : Int
    minute : Int
    second : Int
    hour_offset : Int
    minute_offset : Int
    } derive(Eq, ToJson,
    Debug
    )

    A PDF date with local time-zone offset components.

    The fields mirror PDF's D:YYYYMMDDHHmmSSOHH'mm' representation. Month and day default to 1 when omitted during parsing; time fields default to zero.

    PdfDate::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfDate::equal(PdfDate, PdfDate) -> Bool

    PdfDate::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfDate::not_equal(x : PdfDate, y : PdfDate) -> Bool

    PdfDate::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfDate::to_json(PdfDate) -> Json

    PdfDate::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfDate::to_repr(PdfDate) ->
    Repr

    PdfStrftimeTime

    pub(all) struct PdfStrftimeTime {
    tm_sec : Int
    tm_min : Int
    tm_hour : Int
    tm_mday : Int
    tm_mon : Int
    tm_year : Int
    tm_wday : Int
    tm_yday : Int
    tm_isdst : Bool
    } derive(Eq, ToJson,
    Debug
    )

    Platform-independent time record used by cpdf-style strftime.

    tm_year is years since 1900 and tm_mon is zero-based, matching C/Unix struct tm and OCaml's Unix.tm.

    PdfStrftimeTime::equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfStrftimeTime::equal(PdfStrftimeTime, PdfStrftimeTime) -> Bool

    PdfStrftimeTime::not_equal

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfStrftimeTime::not_equal(x : PdfStrftimeTime, y : PdfStrftimeTime) -> Bool

    PdfStrftimeTime::to_json

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfStrftimeTime::to_json(PdfStrftimeTime) -> Json

    PdfStrftimeTime::to_repr

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn PdfStrftimeTime::to_repr(PdfStrftimeTime) ->
    Repr

    pdf_bytes_of_date

    fn pdf_bytes_of_date(date : PdfDate) -> Bytes raise
    PdfError

    Formats a PDF date as an owned PDF byte string.

    Raises @core.PdfError::BadDate if any field is outside the representable PDF date ranges.

    pdf_date_of_bytes

    fn pdf_date_of_bytes(bytes : Bytes) -> PdfDate raise
    PdfError

    Parses a PDF date from owned PDF bytes.

    pdf_date_of_string

    fn pdf_date_of_string(text : String) -> PdfDate raise
    PdfError

    Parses a PDF date from an ASCII string.

    Raises @core.PdfError::BadDate for malformed or out-of-range dates.

    pdf_date_of_view

    fn pdf_date_of_view(bytes : BytesView) -> PdfDate raise
    PdfError

    Parses a PDF date from a byte view.

    Both strings with and without the D: prefix are accepted. Missing optional date fields use the PDF defaults described on PdfDate. Raises @core.PdfError::BadDate for malformed or out-of-range dates.

    pdf_dummy

    let pdf_dummy : PdfStrftimeTime

    Source-spelled cpdf dummy strftime time value.

    pdf_strftime_dummy_time

    fn pdf_strftime_dummy_time() -> PdfStrftimeTime

    Dummy cpdf strftime time value.

    pdf_strftime_with_time

    fn pdf_strftime_with_time(time : PdfStrftimeTime, text : String) -> String

    Format text using cpdf's C-style strftime subset and an explicit time.

    This follows the OCaml implementation's replacement order and field semantics, including zero-based %j and the absence of a %s replacement.

    pdf_string_of_date

    fn pdf_string_of_date(date : PdfDate) -> String raise
    PdfError

    Formats a PDF date as an ASCII string in PDF date syntax.

    Raises @core.PdfError::BadDate if any field is outside the representable PDF date ranges.