Skip to main content

Workdays

Struct Workdays 

Source
pub struct Workdays {
    pub conn: Connection,
}
Expand description

Database manager for workday operations and time tracking functionality.

The Workdays struct provides a comprehensive interface for managing daily work sessions, including creation, modification, and querying of workday records. It handles database connections, ensures data integrity, and provides efficient access patterns for time tracking operations.

§Design Principles

  • One Session Per Day: Each calendar date has at most one workday record
  • Local Timezone: All timestamps use local timezone for user clarity
  • Automatic Tracking: Supports both automatic and manual time entry
  • Data Integrity: Enforces constraints and validation for reliable tracking

§Connection Management

Each instance maintains its own database connection and ensures the workdays table schema is properly initialized during construction.

Fields§

§conn: Connection

Direct database connection for workday operations.

Provides transactional access to the workdays table with optimized performance for time tracking queries and updates.

Implementations§

Source§

impl Workdays

Source

pub fn new() -> Result<Self>

Creates a new Workdays manager and initializes the database schema.

This constructor establishes a database connection, ensures the workdays table exists with proper constraints, and prepares the manager for time tracking operations. Schema creation is idempotent and safe for repeated initialization.

§Returns

Returns a new Workdays instance ready for workday management operations, or an error if database initialization fails.

§Example
use kasl::db::workdays::Workdays;

let mut workdays = Workdays::new()?;
// Ready for workday tracking
§Database Integration

The workdays table schema is created if it doesn’t exist, ensuring the manager can operate regardless of database initialization order. This provides robustness in different deployment scenarios.

§Errors

Returns an error if:

  • Database connection cannot be established
  • Schema creation fails due to permissions or corruption
  • Table initialization encounters constraint violations
Source

pub fn insert_start(&mut self, date: NaiveDate) -> Result<()>

Records the start of a work session for the specified date.

This method creates a new workday record with the current timestamp as the start time, or does nothing if a workday already exists for the given date. This prevents duplicate workday records while allowing safe repeated calls to start tracking.

§Duplicate Handling

The method checks for existing workday records before insertion to prevent database constraint violations. If a workday already exists for the specified date, the operation succeeds without modification.

§Timezone Consistency

Uses local timezone for timestamp recording to ensure consistency with user expectations and interface displays. All workday times are recorded in the system’s local timezone.

§Arguments
  • date - Calendar date for which to start work session tracking
§Returns

Returns Ok(()) if the start time is recorded or already exists, or an error if the database operation fails.

§Example
use chrono::Local;

let mut workdays = Workdays::new()?;
let today = Local::now().date_naive();
workdays.insert_start(today)?; // Start tracking work for today
§Idempotency

This operation is idempotent - calling it multiple times with the same date has the same effect as calling it once. This makes it safe for use in automatic tracking systems.

Source

pub fn insert_end(&mut self, date: NaiveDate) -> Result<()>

Records the end of a work session for the specified date.

This method updates an existing workday record by setting the end timestamp to the current time. It marks the completion of a work session and enables duration calculations for the workday.

§Prerequisites

The workday must already exist (created via insert_start) for this operation to succeed. The method updates the existing record rather than creating a new one, maintaining data integrity.

§Completion Semantics

Once a workday has an end time, it represents a completed work session for that date. The end time can be modified later using time adjustment methods if corrections are needed.

§Arguments
  • date - Calendar date for which to end work session tracking
§Returns

Returns Ok(()) if the end time is recorded successfully, or an error if no workday exists for the date or the database operation fails.

§Example
use chrono::Local;

let mut workdays = Workdays::new()?;
let today = Local::now().date_naive();

// Start and end a work session
workdays.insert_start(today)?;
// ... work happens ...
workdays.insert_end(today)?; // Mark work as completed
§Error Conditions
  • No workday record exists for the specified date
  • Database connection or constraint failures
  • Concurrent modification conflicts
Source

pub fn fetch(&mut self, date: NaiveDate) -> Result<Option<Workday>>

Retrieves a complete workday record for the specified date.

This method fetches detailed workday information including all temporal data and metadata for a specific calendar date. It provides the primary mechanism for accessing workday details for analysis and reporting.

§Data Parsing

The method handles automatic conversion from database string formats to appropriate Rust types (NaiveDate, NaiveDateTime), providing type safety and convenience for downstream operations.

§Return Semantics
  • Some(Workday): Complete workday record found for the date
  • None: No workday exists for the specified date
  • Error: Database access or parsing failures
§Arguments
  • date - Calendar date for which to retrieve workday information
§Returns

Returns Some(Workday) if a record exists, None if no workday is found for the date, or an error if the database query fails.

§Example
use chrono::Local;

let mut workdays = Workdays::new()?;
let today = Local::now().date_naive();

if let Some(workday) = workdays.fetch(today)? {
    println!("Work started at: {}", workday.start);
    if let Some(end_time) = workday.end {
        println!("Work ended at: {}", end_time);
    } else {
        println!("Work session is still active");
    }
} else {
    println!("No work session recorded for today");
}
§Data Integrity

The method assumes well-formed timestamp data in the database and will return errors if timestamp parsing fails due to data corruption or unexpected format changes.

Source

pub fn fetch_month(&mut self, date: NaiveDate) -> Result<Vec<Workday>>

Retrieves all workdays within the calendar month containing the specified date.

This method fetches workday records for an entire month using SQL date functions to determine month boundaries. It provides efficient bulk access to workday data for monthly reporting, productivity analysis, and trend identification.

§Month Calculation

The method uses SQL strftime functions to extract year-month components and match them against the target date’s month. This approach handles month boundaries correctly across different year transitions.

§Result Processing

All workdays are loaded into memory and returned as a vector, providing convenient access for analysis operations. The results maintain chronological order for consistent processing.

§Arguments
  • date - Any date within the target month for workday retrieval
§Returns

Returns a vector of all workdays in the same month as the specified date, or an error if the database query or parsing fails.

§Example
use chrono::Local;

let mut workdays = Workdays::new()?;
let current_month = Local::now().date_naive();

let monthly_workdays = workdays.fetch_month(current_month)?;
println!("Found {} workdays this month", monthly_workdays.len());

for workday in monthly_workdays {
    if let Some(end_time) = workday.end {
        let duration = end_time - workday.start;
        println!("Date: {}, Duration: {:?}", workday.date, duration);
    }
}
§Performance Considerations
  • Loads all monthly workdays into memory simultaneously
  • Efficient for typical monthly workday counts (20-30 records)
  • May need optimization for very large historical datasets
  • Consider pagination for bulk historical data processing
§Use Cases
  • Monthly productivity reports
  • Work pattern analysis and trend identification
  • Timesheet generation and validation
  • Historical work data export and backup
Source

pub fn update_start( &mut self, date: NaiveDate, new_start: NaiveDateTime, ) -> Result<()>

Updates the start time of an existing workday to a specific timestamp.

This method provides manual adjustment capabilities for correcting automatic time tracking errors or implementing manual time entry scenarios. It modifies the start timestamp while preserving all other workday properties and relationships.

§Time Adjustment Use Cases
  • Correcting automatic tracking start times that were recorded incorrectly
  • Manual time entry for workdays that weren’t automatically tracked
  • Adjusting for delayed system startup or application launch
  • Retroactive time corrections based on external time records
§Data Validation

The method validates that the workday exists before attempting the update and returns an error if no matching record is found. This ensures referential integrity and provides clear error feedback.

§Arguments
  • date - Calendar date of the workday to modify
  • new_start - New start timestamp to apply to the workday
§Returns

Returns Ok(()) if the update succeeds, or an error if the workday doesn’t exist or the database operation fails.

§Example
use chrono::{Local, NaiveDateTime};

let mut workdays = Workdays::new()?;
let today = Local::now().date_naive();

// Correct start time to 9:00 AM
let corrected_start = NaiveDateTime::parse_from_str(
    &format!("{} 09:00:00", today.format("%Y-%m-%d")),
    "%Y-%m-%d %H:%M:%S"
)?;

workdays.update_start(today, corrected_start)?;
§Error Conditions
  • No workday exists for the specified date
  • Database constraint violations or connection failures
  • Invalid timestamp format or timezone issues
Source

pub fn update_end( &mut self, date: NaiveDate, new_end: Option<NaiveDateTime>, ) -> Result<()>

Updates the end time of an existing workday or clears it to mark as ongoing.

This method provides flexible end time management, supporting both specific timestamp updates and clearing end times to mark workdays as ongoing or incomplete. It enables comprehensive time adjustment and correction capabilities.

§Operation Modes
  • Set End Time: Some(timestamp) sets a specific completion time
  • Clear End Time: None removes the end time, marking as ongoing
  • Correction: Modify existing end times for accuracy improvements
§State Transitions

The method supports all valid workday state transitions:

  • Completed → Ongoing (clear end time)
  • Ongoing → Completed (set end time)
  • Completed → Completed (adjust end time)
§Arguments
  • date - Calendar date of the workday to modify
  • new_end - New end timestamp (Some) or clear end time (None)
§Returns

Returns Ok(()) if the update succeeds, or an error if the workday doesn’t exist or the database operation fails.

§Example
use chrono::{Local, NaiveDateTime};

let mut workdays = Workdays::new()?;
let today = Local::now().date_naive();

// Set specific end time
let end_time = NaiveDateTime::parse_from_str(
    &format!("{} 17:30:00", today.format("%Y-%m-%d")),
    "%Y-%m-%d %H:%M:%S"
)?;
workdays.update_end(today, Some(end_time))?;

// Clear end time (mark as ongoing)
workdays.update_end(today, None)?;
§Data Consistency

The method ensures database consistency by validating workday existence and providing clear error feedback for failed operations. This maintains data integrity across time adjustment operations.

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more