streamd timesheet report --use-minutes #79

Closed
opened 2026-04-03 18:22:06 +02:00 by kfickel · 2 comments
Owner

If the --minutes-flag is set, the time is displayed with minuts (8:30) instead of hours with fractions (8.5) everywhere.

If the --minutes-flag is set, the time is displayed with minuts (8:30) instead of hours with fractions (8.5) everywhere.
Author
Owner

Implementation Plan

Overview

Add a --minutes / -m flag to the streamd timesheet command that displays time as HH:MM (e.g., 8:30) instead of decimal hours (e.g., 8.5h).

Files to Modify

File Purpose
src/cli/args.rs Add --minutes / -m flag to Timesheet command
src/main.rs Pass flag value to timesheet run function
src/cli/commands/timesheet.rs Update formatting functions to support minutes display

Implementation Steps

Step 1: Add CLI flag in src/cli/args.rs

Convert Timesheet from a unit variant to a struct variant with the flag:

/// Display extracted timesheets
Timesheet {
    /// Display time as minutes (HH:MM) instead of decimal hours (H.Hh)
    #[arg(short, long)]
    minutes: bool,
},

Step 2: Update src/main.rs to pass the flag

Modify the match arm for Commands::Timesheet to extract and pass the minutes flag to the run() function.

Step 3: Update formatting functions in src/cli/commands/timesheet.rs

3a. Update function signature:

pub fn run(base_folder: &str, use_minutes: bool) -> Result<(), Box<dyn Error>>

3b. Modify format_hours() to support minutes format:

fn format_hours(hours: f64, use_minutes: bool) -> String {
    if use_minutes {
        let total_minutes = (hours * 60.0).round() as i32;
        let h = total_minutes.abs() / 60;
        let m = total_minutes.abs() % 60;
        format!("{}:{:02}", h, m)
    } else {
        format!("{:.1}h", hours)
    }
}

3c. Modify format_diff() to support minutes format:

fn format_diff(hours: f64, use_minutes: bool) -> String {
    if use_minutes {
        let total_minutes = (hours * 60.0).round() as i32;
        let h = total_minutes.abs() / 60;
        let m = total_minutes.abs() % 60;
        let sign = if hours >= 0.0 { "+" } else { "-" };
        format!("{}{}:{:02}", sign, h, m)
    } else {
        if hours >= 0.0 {
            format!("+{:.1}h", hours)
        } else {
            format!("{:.1}h", hours)
        }
    }
}

3d. Update all call sites (approximately 10 locations):

  • Line ~81: Month header diff
  • Lines ~102-104: Daily report columns (expected, actual, diff)
  • Lines ~137-139: Monthly totals row
  • Line ~150: Cumulative balance display
  • Lines ~219-222: Warning messages

Step 4: Update tests

Add unit tests for the new formatting behavior:

  • Test format_hours() with use_minutes=true for various values
  • Test format_diff() with use_minutes=true for positive and negative values
  • Test edge cases: 0 hours, exactly 30 minutes, negative values

Example Output

Current (decimal hours):

2026-04-01 | 8.0h | 8.5h | +0.5h

With --minutes flag:

2026-04-01 | 8:00 | 8:30 | +0:30

Testing

cargo test                           # Run all tests
cargo clippy                         # Lint check
cargo run -- timesheet               # Test default behavior
cargo run -- timesheet --minutes     # Test minutes format
cargo run -- timesheet -m            # Test short flag

Notes

  • Negative differences displayed as -1:30 (minus sign before time)
  • Minutes are rounded to nearest whole minute
  • No changes needed to data structures (DayReport, MonthReport) - only display formatting changes
  • Column alignment may vary slightly between formats due to different string widths
## Implementation Plan ### Overview Add a `--minutes` / `-m` flag to the `streamd timesheet` command that displays time as `HH:MM` (e.g., `8:30`) instead of decimal hours (e.g., `8.5h`). ### Files to Modify | File | Purpose | |------|---------| | `src/cli/args.rs` | Add `--minutes` / `-m` flag to Timesheet command | | `src/main.rs` | Pass flag value to timesheet run function | | `src/cli/commands/timesheet.rs` | Update formatting functions to support minutes display | ### Implementation Steps #### Step 1: Add CLI flag in `src/cli/args.rs` Convert `Timesheet` from a unit variant to a struct variant with the flag: ```rust /// Display extracted timesheets Timesheet { /// Display time as minutes (HH:MM) instead of decimal hours (H.Hh) #[arg(short, long)] minutes: bool, }, ``` #### Step 2: Update `src/main.rs` to pass the flag Modify the match arm for `Commands::Timesheet` to extract and pass the `minutes` flag to the `run()` function. #### Step 3: Update formatting functions in `src/cli/commands/timesheet.rs` **3a. Update function signature:** ```rust pub fn run(base_folder: &str, use_minutes: bool) -> Result<(), Box<dyn Error>> ``` **3b. Modify `format_hours()` to support minutes format:** ```rust fn format_hours(hours: f64, use_minutes: bool) -> String { if use_minutes { let total_minutes = (hours * 60.0).round() as i32; let h = total_minutes.abs() / 60; let m = total_minutes.abs() % 60; format!("{}:{:02}", h, m) } else { format!("{:.1}h", hours) } } ``` **3c. Modify `format_diff()` to support minutes format:** ```rust fn format_diff(hours: f64, use_minutes: bool) -> String { if use_minutes { let total_minutes = (hours * 60.0).round() as i32; let h = total_minutes.abs() / 60; let m = total_minutes.abs() % 60; let sign = if hours >= 0.0 { "+" } else { "-" }; format!("{}{}:{:02}", sign, h, m) } else { if hours >= 0.0 { format!("+{:.1}h", hours) } else { format!("{:.1}h", hours) } } } ``` **3d. Update all call sites** (approximately 10 locations): - Line ~81: Month header diff - Lines ~102-104: Daily report columns (expected, actual, diff) - Lines ~137-139: Monthly totals row - Line ~150: Cumulative balance display - Lines ~219-222: Warning messages #### Step 4: Update tests Add unit tests for the new formatting behavior: - Test `format_hours()` with `use_minutes=true` for various values - Test `format_diff()` with `use_minutes=true` for positive and negative values - Test edge cases: 0 hours, exactly 30 minutes, negative values ### Example Output **Current (decimal hours):** ``` 2026-04-01 | 8.0h | 8.5h | +0.5h ``` **With `--minutes` flag:** ``` 2026-04-01 | 8:00 | 8:30 | +0:30 ``` ### Testing ```bash cargo test # Run all tests cargo clippy # Lint check cargo run -- timesheet # Test default behavior cargo run -- timesheet --minutes # Test minutes format cargo run -- timesheet -m # Test short flag ``` ### Notes - Negative differences displayed as `-1:30` (minus sign before time) - Minutes are rounded to nearest whole minute - No changes needed to data structures (DayReport, MonthReport) - only display formatting changes - Column alignment may vary slightly between formats due to different string widths
kfickel added the
planned
label 2026-04-03 18:27:54 +02:00
Author
Owner

Implementation Summary

PR: #82
Time taken: ~10 minutes
Tokens used: ~15k

What was done

Implemented the -m/--minutes flag exactly as planned. The changes were straightforward:

  1. Converted Timesheet CLI variant from a unit to a struct variant with a minutes: bool flag
  2. Added use_minutes: bool parameter to format_hours() and format_diff(), then propagated it through print_month(), print_cumulative_balance(), print_warnings(), and run()
  3. Added 8 unit tests covering decimal and minutes formatting for both positive, negative, and zero values

Findings

  • The OutsidePeriod warning used an inline {:.1}h format literal rather than calling format_hours() — updated it to use format_hours() for consistency
  • Pre-commit rustfmt hook required a formatting pass before committing; otherwise the implementation was clean on the first build
## Implementation Summary **PR:** #82 **Time taken:** ~10 minutes **Tokens used:** ~15k ### What was done Implemented the `-m`/`--minutes` flag exactly as planned. The changes were straightforward: 1. Converted `Timesheet` CLI variant from a unit to a struct variant with a `minutes: bool` flag 2. Added `use_minutes: bool` parameter to `format_hours()` and `format_diff()`, then propagated it through `print_month()`, `print_cumulative_balance()`, `print_warnings()`, and `run()` 3. Added 8 unit tests covering decimal and minutes formatting for both positive, negative, and zero values ### Findings - The `OutsidePeriod` warning used an inline `{:.1}h` format literal rather than calling `format_hours()` — updated it to use `format_hours()` for consistency - Pre-commit rustfmt hook required a formatting pass before committing; otherwise the implementation was clean on the first build
Sign in to join this conversation.
No labels
planned
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference: kfickel/streamd#79
No description provided.