Implement opal-task Phase 1: Database foundation
- Add SQLite database with schema for tasks, tags, and working_set - Implement config management with Viper (opal.yml) - Create Task struct with proper types (*time.Time, Priority int) - Add database migration system - Implement recurrence pattern parsing (1d, 1w, 1m, 1y) - Setup project structure with cmd/ and internal/engine/ - Add dependencies: sqlite3, uuid, cobra, viper, color
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ParseRecurrencePattern converts "1w", "2d", "1m" to time.Duration
|
||||
func ParseRecurrencePattern(pattern string) (time.Duration, error) {
|
||||
if len(pattern) < 2 {
|
||||
return 0, fmt.Errorf("invalid recurrence pattern: %s", pattern)
|
||||
}
|
||||
|
||||
numStr := pattern[:len(pattern)-1]
|
||||
unit := pattern[len(pattern)-1]
|
||||
|
||||
num, err := strconv.Atoi(numStr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid number in pattern: %s", pattern)
|
||||
}
|
||||
|
||||
switch unit {
|
||||
case 'd':
|
||||
return time.Duration(num) * 24 * time.Hour, nil
|
||||
case 'w':
|
||||
return time.Duration(num) * 7 * 24 * time.Hour, nil
|
||||
case 'm':
|
||||
// Approximate: 30 days
|
||||
return time.Duration(num) * 30 * 24 * time.Hour, nil
|
||||
case 'y':
|
||||
// Approximate: 365 days
|
||||
return time.Duration(num) * 365 * 24 * time.Hour, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("unknown unit: %c (use d/w/m/y)", unit)
|
||||
}
|
||||
}
|
||||
|
||||
// FormatRecurrenceDuration converts time.Duration back to "1w", "2d" format
|
||||
func FormatRecurrenceDuration(d time.Duration) string {
|
||||
days := int(d.Hours() / 24)
|
||||
|
||||
if days%365 == 0 && days/365 > 0 {
|
||||
return fmt.Sprintf("%dy", days/365)
|
||||
}
|
||||
if days%30 == 0 && days/30 > 0 {
|
||||
return fmt.Sprintf("%dm", days/30)
|
||||
}
|
||||
if days%7 == 0 && days/7 > 0 {
|
||||
return fmt.Sprintf("%dw", days/7)
|
||||
}
|
||||
return fmt.Sprintf("%dd", days)
|
||||
}
|
||||
|
||||
// CalculateNextDue calculates next due date based on current and recurrence
|
||||
func CalculateNextDue(currentDue time.Time, recurrence time.Duration) time.Time {
|
||||
return currentDue.Add(recurrence)
|
||||
}
|
||||
|
||||
// SpawnNextInstance creates a new task instance from completed recurring task
|
||||
// This will be implemented after we have the CRUD operations
|
||||
func SpawnNextInstance(completedInstance *Task) error {
|
||||
if completedInstance.ParentUUID == nil {
|
||||
return fmt.Errorf("task is not a recurring instance")
|
||||
}
|
||||
|
||||
// TODO: Implement after GetTask is available
|
||||
return fmt.Errorf("not implemented yet")
|
||||
}
|
||||
Reference in New Issue
Block a user