first commit

This commit is contained in:
Blake Ridgway 2025-03-19 07:08:52 -05:00
commit 43f13205bf
2 changed files with 192 additions and 0 deletions

69
README.md Normal file
View file

@ -0,0 +1,69 @@
# TimeLogix
TimeLogix is a simple, intuitive Tkinter-based time tracking application designed to help contractors log and manage their working hours effectively. This tool was created so I could keep proper track of time worked under a contract for a company, ensuring accurate record-keeping and easy export of session data for billing and reporting purposes.
## Features
- **Start/Stop Tracking:** Easily log your work sessions with start and stop buttons.
- **Session Logging:** View session start times, end times, and durations both in \(H:MM:SS\) and decimal hours.
- **CSV Export:** Export your session data to a CSV file for further processing or billing.
- **Simple UI:** A clean and minimal user interface built using Tkinter.
## Requirements
- Python 3.x
- Tkinter (usually included with standard Python installations)
## Installation
1. **Clone the Repository:**
```bash
git clone https://github.com/yourusername/timelogix.git
cd timelogix
```
2. **(Optional) Create and Activate a Virtual Environment:**
```bash
python -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
```
3. **Install Dependencies:**
There are no additional dependencies beyond the Python Standard Library. However, ensure you have the latest version of Python installed.
## Usage
Run the application using Python:
```bash
python time_logix.py
```
### How to Use
1. **Start Tracking:**
- Click the **Start Tracking** button to log the starting time of your work session.
2. **Stop Tracking:**
- Click the **Stop Tracking** button to end the session. The app will display and log the duration in both formats, e.g., `1:30:00` and `1.50 hours`.
3. **Export Sessions:**
- Once youre finished working, click the **Export Sessions** button to save your session data into `working_sessions.csv`.
## Customizations
- **Decimal Hours:** The app calculates hours worked in decimal format using a helper function.
- **CSV File Export:** Sessions are exported to a CSV file with headers: `Start Time`, `End Time`, `Duration (H:MM:SS)`, and `Decimal Hours`.
## Contributing
Contributions are welcome! Feel free to fork the repository, make changes, and submit pull requests. For any major changes, please open an issue first to discuss what you would like to change.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Contact
For any questions or suggestions, please contact [blake@blakeridgway.com](mailto:blake@blakeridgway.com).

123
time_logix.py Normal file
View file

@ -0,0 +1,123 @@
import tkinter as tk
from tkinter import messagebox
from datetime import datetime
import csv
import os
class TimeLogix(tk.Tk):
def __init__(self):
super().__init__()
self.title("Time Logix")
self.geometry("450x350")
self.start_time = None
self.tracking = False
self.sessions = []
self.create_widgets()
def create_widgets(self):
self.status_label = tk.Label(self, text="Status: Not Tracking", font=("Helvetica", 12))
self.status_label.pack(pady=10)
self.start_button = tk.Button(
self, text="Start Tracking", width=20, command=self.start_tracking
)
self.start_button.pack(pady=5)
self.stop_button = tk.Button(
self, text="Stop Tracking", width=20, command=self.stop_tracking, state=tk.DISABLED
)
self.stop_button.pack(pady=5)
self.export_button = tk.Button(
self, text="Export Sessions", width=20, command=self.export_sessions
)
self.export_button.pack(pady=5)
self.log_text = tk.Text(self, height=10, state=tk.DISABLED)
self.log_text.pack(pady=10, padx=10, fill='both', expand=True)
def log_message(self, message):
"""Append message to the log text widget."""
self.log_text.configure(state=tk.NORMAL)
self.log_text.insert(tk.END, f"{message}\n")
self.log_text.configure(state=tk.DISABLED)
self.log_text.see(tk.END)
def start_tracking(self):
if self.tracking:
messagebox.showwarning("Warning", "Already tracking!")
return
self.start_time = datetime.now()
self.tracking = True
self.status_label.config(
text=f"Status: Tracking started at {self.start_time.strftime('%H:%M:%S')}"
)
self.log_message(f"Started at: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")
self.start_button.config(state=tk.DISABLED)
self.stop_button.config(state=tk.NORMAL)
def stop_tracking(self):
if not self.tracking:
messagebox.showwarning("Warning", "Not currently tracking!")
return
end_time = datetime.now()
duration = end_time - self.start_time
self.sessions.append((self.start_time, end_time, duration))
self.tracking = False
self.status_label.config(text="Status: Not Tracking")
decimal_hours = self.get_decimal_hours(duration)
self.log_message(
f"Stopped at: {end_time.strftime('%Y-%m-%d %H:%M:%S')}, Duration: {self.format_duration(duration)} "
f"({decimal_hours:.2f} hours)"
)
self.start_button.config(state=tk.NORMAL)
self.stop_button.config(state=tk.DISABLED)
def format_duration(self, duration):
"""Format duration as H:MM:SS"""
total_seconds = int(duration.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
return f"{hours}:{minutes:02d}:{seconds:02d}"
def get_decimal_hours(self, duration):
"""Convert a timedelta duration to decimal hours."""
total_hours = duration.total_seconds() / 3600
return total_hours
def export_sessions(self):
if not self.sessions:
messagebox.showinfo("Info", "No sessions to export.")
return
filename = "working_sessions.csv"
try:
file_exists = os.path.isfile(filename)
with open(filename, mode="a", newline="") as csvfile:
writer = csv.writer(csvfile)
if not file_exists:
writer.writerow([
"Start Time", "End Time",
"Duration (H:MM:SS)", "Decimal Hours"
])
for session in self.sessions:
start, end, duration = session
writer.writerow([
start.strftime("%Y-%m-%d %H:%M:%S"),
end.strftime("%Y-%m-%d %H:%M:%S"),
self.format_duration(duration),
f"{self.get_decimal_hours(duration):.2f}"
])
messagebox.showinfo("Export Successful", f"Sessions exported to {filename}")
self.sessions.clear()
except Exception as e:
messagebox.showerror("Error", f"Failed to export: {e}")
if __name__ == "__main__":
app = TimeLogix()
app.mainloop()