Skip to main content

AssessmentClock

Struct AssessmentClock 

Source
pub struct AssessmentClock {
    pub law_in_force_on: NaiveDate,
    pub computed_at: DateTime<Utc>,
}
Expand description

The two dates a compliance computation needs. They are never the same field.

EU staged obligations attach at a regulated triggering event — for Regulation (EU) 2023/1542 Articles 7, 8 and 10 that is placing on the market or putting into service. Which law governs a given product is therefore fixed at that moment, and does not change when the product is reassessed years later. A battery lawfully placed on the market in 2030 does not acquire the 18 August 2031 minimums by being audited in 2033.

There is deliberately no AssessmentClock::now(). A wall-clock constructor is precisely the mistake this type exists to prevent: it would let every determination silently re-derive the governing law from whichever day the calculation happened to run.

Fields§

§law_in_force_on: NaiveDate

Which law applies. Derived from the regulated triggering event — never from today’s date.

§computed_at: DateTime<Utc>

When this computation ran. Receipt provenance only; this never selects a ruleset.

Implementations§

Source§

impl AssessmentClock

Source

pub fn placed_on(law_in_force_on: NaiveDate) -> Self

Build a clock for a product whose governing law was fixed on law_in_force_on, computed now.

The wall clock supplies computed_at and nothing else. law_in_force_on must come from the product’s own record — the passport’s placing-on-market date — and never from Utc::now().

Examples found in repository?
examples/calculate_metrics.rs (line 15)
12fn main() {
13    // The date the governing law attached to this product. In a real caller this
14    // comes from the passport's placing-on-market date, never from the clock.
15    let clock = AssessmentClock::placed_on(NaiveDate::from_ymd_opt(2026, 1, 1).unwrap());
16
17    // Cradle-to-gate CO₂e for a small battery (materials + manufacturing energy).
18    let footprint = co2e::calculate(
19        &Co2eInputs {
20            materials: vec![
21                MaterialFootprint {
22                    mass_kg: 0.5,
23                    emission_factor_kg_co2e_per_kg: 8.0, // e.g. recycled aluminium
24                },
25                MaterialFootprint {
26                    mass_kg: 0.2,
27                    emission_factor_kg_co2e_per_kg: 3.0,
28                },
29            ],
30            energy_kwh: 1.5,
31            grid_factor_kg_co2e_per_kwh: 0.4,
32        },
33        &CradleToGateRuleset,
34        clock,
35    )
36    .expect("valid inputs");
37
38    println!(
39        "CO₂e: {:.2} kg  (materials {:.2} + energy {:.2})  stages={:?}  receipt={}",
40        footprint.total_co2e_kg,
41        footprint.material_co2e_kg,
42        footprint.energy_co2e_kg,
43        footprint.declared_stages,
44        footprint.receipt.receipt_id,
45    );
46    for (i, line) in footprint.material_breakdown.iter().enumerate() {
47        println!(
48            "  material[{i}]: {:.3} kg × {:.3} kg CO₂e/kg = {:.3} kg CO₂e",
49            line.mass_kg, line.emission_factor_kg_co2e_per_kg, line.co2e_kg
50        );
51    }
52
53    // Simplified repairability heuristic band (A–E) for a smartphone — not the
54    // EU 2023/1669 regulatory class.
55    let rep = repairability::calculate(
56        &RepairabilityInputs {
57            disassembly: 2,
58            spare_parts: 2,
59            repair_info: 1,
60            diagnostic_tools: 1,
61            software_updatability: 2,
62            customer_support: 1,
63        },
64        &SimplifiedRepairabilityHeuristic,
65        clock,
66    )
67    .expect("valid inputs");
68
69    println!(
70        "Repairability: {}  ({:.2}/10)  ruleset={}@{}",
71        rep.class, rep.numeric_score, rep.receipt.ruleset_id, rep.receipt.ruleset_version,
72    );
73    let c = &rep.contributions;
74    println!(
75        "  disassembly={:.2} spare_parts={:.2} repair_info={:.2} \
76         diagnostic={:.2} software={:.2} support={:.2}",
77        c.disassembly,
78        c.spare_parts,
79        c.repair_info,
80        c.diagnostic_tools,
81        c.software_updatability,
82        c.customer_support,
83    );
84}
Source

pub const fn new(law_in_force_on: NaiveDate, computed_at: DateTime<Utc>) -> Self

Fully explicit constructor, pinning both dates.

Re-verifying a stored receipt needs this: reproducing a historical calculation means reproducing the computation timestamp too, not just the governing law.

Trait Implementations§

Source§

impl Clone for AssessmentClock

Source§

fn clone(&self) -> AssessmentClock

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for AssessmentClock

Source§

impl Debug for AssessmentClock

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for AssessmentClock

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for AssessmentClock

Source§

impl PartialEq for AssessmentClock

Source§

fn eq(&self, other: &AssessmentClock) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for AssessmentClock

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for AssessmentClock

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.