1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//! Behavioural helpers shared by `manta-cli` and `manta-server`.
//!
//! The three submodules are intentionally narrow:
//!
//! - [`config`] — locates and parses `cli.toml` / `server.toml`,
//! honouring `MANTA_CLI_CONFIG` / `MANTA_SERVER_CONFIG` and merging
//! `MANTA_*`-prefixed environment overrides. Returns an untyped
//! `::config::Config` so each binary owns its own typed schema.
//! - [`error`] — the [`error::MantaError`] enum returned by every
//! fallible helper in this crate; the server bridges it to its
//! `BackendError` at call sites.
//! - [`log_ops`] — single `configure(...)` entry point both binaries
//! call once at startup to install the tracing subscriber.
/// Date-time format string used for displaying timestamps
/// throughout the application (e.g. "04/03/2026 14:30:00").
pub const DATETIME_FORMAT: &str = "%d/%m/%Y %H:%M:%S";
/// Parse an IMS `created` timestamp into a comparable value.
///
/// CSM returns `created` in more than one shape, so try
/// [`chrono::NaiveDateTime`] first, then [`chrono::DateTime<Local>`],
/// normalising a zoned timestamp to local naive time. Returns `None`
/// when neither parses.
///
/// A zoned timestamp is converted into **this process's** local
/// timezone, so the same input yields a different naive value on hosts
/// in different zones. Callers that compare across the client/server
/// boundary (the CLI renderer vs. the server's date filter) agree on
/// which strings parse, not necessarily on the wall-clock value of a
/// zoned one.
///
/// Lives here rather than in either binary because the server filters
/// on this value (`service::image::get_images`) while the CLI renders
/// it (`output::image`). If the two disagreed on what parses, a row
/// could display a creation date that the filter silently drops.
///
/// ```
/// use manta_shared::common::parse_ims_timestamp;
///
/// // Naive, offset, and the `Z`/fractional-second shapes IMS emits.
/// assert!(parse_ims_timestamp("2026-06-04T12:30:00").is_some());
/// assert!(parse_ims_timestamp("2026-06-04T12:30:00+00:00").is_some());
/// assert!(parse_ims_timestamp("2026-06-04T12:30:00Z").is_some());
/// assert!(parse_ims_timestamp("2026-06-04T12:30:00.643891Z").is_some());
/// assert!(parse_ims_timestamp("not-a-real-date").is_none());
/// ```