Documentation Index
Fetch the complete documentation index at: https://mintlify.com/avsm/httpz/llms.txt
Use this file to discover all available pages before exploring further.
The Date module provides zero-allocation parsing and formatting for HTTP date values per RFC 7231 Section 7.1.1.1. It handles all three accepted HTTP date formats and generates the preferred IMF-fixdate format.
Overview
HTTP uses a restricted subset of date formats for headers like Date, Last-Modified, If-Modified-Since, If-Unmodified-Since, and Expires. This module:
- Parses all three accepted formats
- Returns timestamps as unboxed
float# (Unix seconds since epoch)
- Generates dates in the preferred IMF-fixdate format
- Provides comparison helpers for conditional requests
Format: Sun, 06 Nov 1994 08:49:37 GMTThis is the preferred format for all HTTP date generation.
Format: Sunday, 06-Nov-94 08:49:37 GMTObsolete format with 2-digit year. Accepted for parsing only.
Format: Sun Nov 6 08:49:37 1994ANSI C asctime() format. Accepted for parsing only.
Types
Parse Status
Result status from date parsing.Successfully parsed valid HTTP-date
Invalid date format or out-of-range values
Parsing Functions
parse
val parse : local_ Base_bigstring.t -> Span.t -> #(status * float#)
Parse HTTP-date from buffer span. Automatically detects and parses all three accepted formats.
Buffer containing the date value (marked as local)
Span indicating the date value location in buffer
Returns: Unboxed tuple #(status * float#) where:
- First value is parse status
- Second value is Unix timestamp (seconds since epoch) - only valid if status is
Valid
Example:
(* Parse If-Modified-Since header *)
let if_modified_since = Req.find_header req Header_name.If_modified_since in
match if_modified_since with
| Some span ->
let #(status, timestamp) = Date.parse (Req.buf req) span in
(match status with
| Date.Valid ->
(* Check if resource was modified *)
if Date.is_modified_since ~last_modified:resource.mtime ~if_modified_since:timestamp then
send_full_response ()
else
send_304_not_modified ()
| Date.Invalid ->
(* Ignore malformed date *)
send_full_response ())
| None ->
send_full_response ()
val format : float# -> string
Format Unix timestamp as IMF-fixdate string (allocates).
Unix timestamp (seconds since epoch) as unboxed float
Returns: String in IMF-fixdate format: "Sun, 06 Nov 1994 08:49:37 GMT"
Example:
let now = Unix.gettimeofday () in
let date_str = Date.format (f64 now) in
Printf.printf "Current date: %s\n" date_str
(* Output: Current date: Wed, 04 Mar 2026 12:34:56 GMT *)
Response Writing
val write_date_header : Base_bigstring.t -> off:int16# -> float# -> int16#
Write Date: <timestamp>\r\n header to response buffer.
Returns: New offset after writing.
Example:
let now = f64 (Unix.gettimeofday ()) in
let off = Res.write_status_line buf ~off 200 in
let off = Date.write_date_header buf ~off now in
let off = Res.write_content_length buf ~off content_len in
(* ... *)
write_last_modified
val write_last_modified : Base_bigstring.t -> off:int16# -> float# -> int16#
Write Last-Modified: <timestamp>\r\n header to response buffer.
Last modification timestamp
Returns: New offset after writing.
Example:
let file_stat = Unix.stat filename in
let mtime = f64 file_stat.st_mtime in
let off = Res.write_status_line buf ~off 200 in
let off = Date.write_last_modified buf ~off mtime in
(* ... *)
write_expires
val write_expires : Base_bigstring.t -> off:int16# -> float# -> int16#
Write Expires: <timestamp>\r\n header to response buffer.
Returns: New offset after writing.
Example:
(* Set expiration 1 hour from now *)
let now = Unix.gettimeofday () in
let expires = f64 (now +. 3600.0) in
let off = Res.write_status_line buf ~off 200 in
let off = Date.write_expires buf ~off expires in
(* ... *)
write_http_date
val write_http_date : Base_bigstring.t -> off:int16# -> float# -> int16#
Write formatted HTTP-date at offset without header name or CRLF. Used internally by header writers.
Returns: New offset after writing.
Example:
(* Write custom date header *)
let off = Buf_write.string buf ~off "X-Custom-Date: " in
let off = Date.write_http_date buf ~off timestamp in
let off = Buf_write.crlf buf ~off in
Comparison Helpers
is_modified_since
val is_modified_since : last_modified:float# -> if_modified_since:float# -> bool
Check if resource was modified since the given date. Used for If-Modified-Since header processing.
Resource’s last modification timestamp
Timestamp from If-Modified-Since header
Returns: true if resource has been modified after the if_modified_since date (serve full content), false otherwise (send 304).
Note: HTTP dates have 1-second resolution. Comparison uses > not >= to handle precision correctly.
Example:
(* Handle If-Modified-Since for GET request *)
let handle_if_modified_since req resource =
match Req.find_header req Header_name.If_modified_since with
| Some span ->
let #(status, client_date) = Date.parse (Req.buf req) span in
if status = Date.Valid then
if Date.is_modified_since
~last_modified:resource.mtime
~if_modified_since:client_date
then
(* Resource modified - send full response *)
send_200_with_content resource
else
(* Not modified - send 304 *)
let off = Res.write_status_line buf ~off:(i16 0) 304 in
let off = Date.write_last_modified buf ~off resource.mtime in
let off = Res.crlf buf ~off in
send_response ~len:off
else
(* Invalid date - ignore header *)
send_200_with_content resource
| None ->
send_200_with_content resource
is_unmodified_since
val is_unmodified_since : last_modified:float# -> if_unmodified_since:float# -> bool
Check if resource was not modified since the given date. Used for If-Unmodified-Since header processing.
Resource’s last modification timestamp
Timestamp from If-Unmodified-Since header
Returns: true if resource has NOT been modified after the if_unmodified_since date (safe to proceed), false otherwise (send 412 Precondition Failed).
Example:
(* Handle If-Unmodified-Since for PUT/PATCH request *)
let handle_if_unmodified_since req resource =
match Req.find_header req Header_name.If_unmodified_since with
| Some span ->
let #(status, client_date) = Date.parse (Req.buf req) span in
if status = Date.Valid then
if Date.is_unmodified_since
~last_modified:resource.mtime
~if_unmodified_since:client_date
then
(* Precondition met - proceed with update *)
update_resource resource
else
(* Resource modified - send 412 Precondition Failed *)
let off = Res.write_status_line buf ~off:(i16 0) 412 in
let off = Date.write_last_modified buf ~off resource.mtime in
let off = Res.crlf buf ~off in
send_response ~len:off
else
(* Invalid date - ignore header *)
update_resource resource
| None ->
update_resource resource
Complete Example: Conditional Requests
(* Handle GET request with full conditional logic *)
let handle_conditional_get req resource =
let buf = Req.buf req in
let resource_mtime = resource.last_modified in (* float# *)
(* Check If-Modified-Since *)
let not_modified = match Req.find_header req Header_name.If_modified_since with
| Some span ->
let #(status, client_date) = Date.parse buf span in
if status = Date.Valid then
not (Date.is_modified_since ~last_modified:resource_mtime ~if_modified_since:client_date)
else
false
| None -> false
in
if not_modified then
(* Send 304 Not Modified *)
let off = Res.write_status_line response_buf ~off:(i16 0) 304 in
let now = f64 (Unix.gettimeofday ()) in
let off = Date.write_date_header response_buf ~off now in
let off = Date.write_last_modified response_buf ~off resource_mtime in
let off = Res.crlf response_buf ~off in
send_response ~len:off
else
(* Send full 200 response *)
let off = Res.write_status_line response_buf ~off:(i16 0) 200 in
let now = f64 (Unix.gettimeofday ()) in
let off = Date.write_date_header response_buf ~off now in
let off = Date.write_last_modified response_buf ~off resource_mtime in
let off = Res.write_content_length response_buf ~off (i64 (Int64.of_int resource.content_length)) in
(* Set cache expiration (1 hour) *)
let expires = f64 (Unix.gettimeofday () +. 3600.0) in
let off = Date.write_expires response_buf ~off expires in
let off = Res.crlf response_buf ~off in
let off = write_body response_buf ~off resource.content in
send_response ~len:off
Implementation Notes
- All parsing returns unboxed
float# timestamps for zero-allocation operation
- Date parsing handles leap years correctly
- RFC 850 2-digit years are interpreted as:
00-69 → 2000-2069
70-99 → 1970-1999
- All generated dates use GMT timezone (as required by RFC 7231)
- Leap seconds (
:60) are accepted during parsing
- Comparison functions account for 1-second precision of HTTP dates