Skip to content

Commit d74d82a

Browse files
author
Per-Gunnar Eriksson
committed
Bug fixes
1 parent 48123d6 commit d74d82a

File tree

4 files changed

+79
-38
lines changed

4 files changed

+79
-38
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tt"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
edition = "2024"
55
description = "Timetracker (TT) - a CLI time tracking application"
66
authors = ["pergeri <[email protected]>"]

src/commands/hello.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use anyhow::Result;
2-
use chrono::{Local, NaiveTime, TimeZone};
32

43
use crate::config::Config;
54
use crate::entry::{Entry, HELLO_ENTRY_NAME, MIDNIGHT_SEPARATOR_PREFIX};
@@ -34,20 +33,17 @@ pub fn execute(cli: &crate::Cli, config: &Config) -> Result<()> {
3433

3534
// If needed, add a midnight separator entry
3635
if create_midnight_separator {
37-
// Create a midnight entry at 00:00 of the current day
38-
let midnight_naive = now.date_naive().and_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap());
39-
let midnight = Local.from_local_datetime(&midnight_naive).single().unwrap();
40-
41-
// Create a midnight separator entry
42-
let midnight_entry = Entry::new(
43-
midnight,
36+
// Create a separator entry with current time, not midnight
37+
// This indicates a new day is starting when the hello command is run
38+
let separator_entry = Entry::new(
39+
now,
4440
format!("{}", MIDNIGHT_SEPARATOR_PREFIX),
4541
false,
4642
None
4743
);
4844

4945
// Write the midnight separator to the log file
50-
storage::append_entry(&data_file, &midnight_entry)?;
46+
storage::append_entry(&data_file, &separator_entry)?;
5147
}
5248

5349
// Create a hello entry

src/commands/report.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ pub fn execute(
3535
// Read all entries from the log file
3636
let all_entries = storage::read_entries(&data_file)?;
3737

38+
// Check if we're displaying just today's report (the default case)
39+
let is_today_only = range.start_date == now.date_naive() &&
40+
range.end_date == now.date_naive() &&
41+
date.is_none() && from_date.is_none() &&
42+
to_date.is_none() && month.is_none() &&
43+
week.is_none();
44+
3845
// Filter entries by date range considering midnight separators
3946
let filtered_entries = storage::filter_entries_by_date_range(
4047
&all_entries,
@@ -45,13 +52,18 @@ pub fn execute(
4552
// Convert entries to activities
4653
let mut activities = storage::entries_to_activities(&filtered_entries, Some(range.start_date), Some(range.end_date));
4754

48-
// Filter activities to only include those that fall within our date range
49-
// This ensures we don't include activities from previous days
50-
activities.retain(|activity| {
51-
// Activity end time must be within our date range
52-
let activity_date = activity.end.date_naive();
53-
activity_date >= range.start_date && activity_date <= range.end_date
54-
});
55+
// For today-only reports, ensure we only show activities that occurred today
56+
if is_today_only {
57+
activities.retain(|activity| {
58+
activity.end.date_naive() == now.date_naive()
59+
});
60+
} else {
61+
// For other date ranges, ensure activities fall within the specified range
62+
activities.retain(|activity| {
63+
let activity_date = activity.end.date_naive();
64+
activity_date >= range.start_date && activity_date <= range.end_date
65+
});
66+
}
5567

5668
// Add current activity if requested
5769
if !no_current_activity && !filtered_entries.is_empty() {

src/storage.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use anyhow::{Context, Result};
2-
use chrono::{DateTime, Local, NaiveDate};
2+
use chrono::{DateTime, Local, NaiveDate, TimeZone};
33
use std::fs::{self, File, OpenOptions};
44
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom, Write};
55
use std::path::Path;
66

7-
use crate::entry::{Activity, Entry, MIDNIGHT_SEPARATOR_PREFIX};
7+
use crate::entry::{Activity, Entry, MIDNIGHT_SEPARATOR_PREFIX, HELLO_ENTRY_NAME};
88

99
pub fn read_entries(data_file: &Path) -> Result<Vec<Entry>> {
1010
if !data_file.exists() {
@@ -134,32 +134,58 @@ pub fn entries_to_activities(entries: &[Entry], start_date: Option<NaiveDate>, e
134134
let start_time = entries[i].datetime;
135135
let end_time = entries[i+1].datetime;
136136

137-
// Apply date filtering if specified
138-
// Only include activities that occur within the date range
139-
if let Some(start_date) = start_date {
140-
if end_time.date_naive() < start_date {
141-
continue; // Skip activities that end before the start date
142-
}
143-
}
137+
// Special handling for "hello" entries
138+
// Make the hello entry start at the beginning of the day instead of from the last entry of the previous day
139+
let adjusted_start_time = if entries[i+1].name == HELLO_ENTRY_NAME {
140+
// Use midnight of the current day as the start time for hello entries
141+
let naive_midnight = end_time.date_naive().and_time(chrono::NaiveTime::from_hms_opt(0, 0, 0).unwrap());
142+
Local.from_local_datetime(&naive_midnight).single().unwrap()
143+
} else {
144+
start_time
145+
};
144146

145-
if let Some(end_date) = end_date {
146-
if start_time.date_naive() > end_date {
147-
continue; // Skip activities that start after the end date
148-
}
149-
}
147+
// Activities are defined by their end time (the timestamp when they were recorded)
148+
// The activity belongs to the day of its end timestamp
149+
let activity_date = end_time.date_naive();
150150

151-
// Only include activities where the end time is within the date range
152-
// This ensures only activities that complete within the requested range are shown
151+
// Filter based on date range
153152
if let (Some(start_date), Some(end_date)) = (start_date, end_date) {
154-
let activity_date = end_time.date_naive();
153+
// Only include activities that end within the specified date range
155154
if activity_date < start_date || activity_date > end_date {
156155
continue;
157156
}
157+
158+
// Additional check: if this is for a single day report (default "today" behavior)
159+
// and the start time is from a previous day, make sure it's only from the
160+
// immediately preceding day, unless it's a "hello" entry which we already adjusted
161+
if start_date == end_date && entries[i+1].name != HELLO_ENTRY_NAME {
162+
let start_activity_date = adjusted_start_time.date_naive();
163+
if start_activity_date < activity_date {
164+
// Calculate days between the dates
165+
let days_between = (activity_date - start_activity_date).num_days();
166+
if days_between > 1 {
167+
continue; // Skip activities that started more than one day before
168+
}
169+
}
170+
}
171+
} else {
172+
// Apply date filtering if only one date boundary is specified
173+
if let Some(start_date) = start_date {
174+
if activity_date < start_date {
175+
continue; // Skip activities that end before the start date
176+
}
177+
}
178+
179+
if let Some(end_date) = end_date {
180+
if activity_date > end_date {
181+
continue; // Skip activities that end after the end date
182+
}
183+
}
158184
}
159185

160186
let activity = Activity::new(
161187
entries[i+1].name.clone(),
162-
start_time,
188+
adjusted_start_time, // Use the adjusted start time
163189
end_time,
164190
false,
165191
entries[i+1].comment.clone(),
@@ -181,15 +207,22 @@ pub fn filter_entries_by_date_range(entries: &[Entry], start_date: NaiveDate, en
181207

182208
// Find the last entry before the start date (needed for calculating the first activity's duration)
183209
// This handles the case where an activity starts before our date range but ends within it
210+
// Only include this entry if it's from the same day as start_date or from the immediate previous day
184211
let mut last_entry_before_range = None;
185212
for entry in entries.iter().rev() {
186-
if entry.datetime.date_naive() < start_date {
187-
last_entry_before_range = Some(entry.clone());
213+
let entry_date = entry.datetime.date_naive();
214+
if entry_date < start_date {
215+
// Only include the previous entry if it's from the same day or immediately before
216+
// This prevents showing activities from days far in the past
217+
let days_between = (start_date - entry_date).num_days();
218+
if days_between <= 1 {
219+
last_entry_before_range = Some(entry.clone());
220+
}
188221
break;
189222
}
190223
}
191224

192-
// If we found a last entry before the range, include it
225+
// If we found a valid last entry before the range, include it
193226
if let Some(entry) = last_entry_before_range {
194227
filtered_entries.push(entry);
195228
}

0 commit comments

Comments
 (0)