1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5// Package dateutil provides natural language date parsing for lune commands.
6package dateutil
7
8import (
9 "fmt"
10 "time"
11
12 "git.secluded.site/go-lunatask"
13 "github.com/KarpelesLab/strtotime"
14)
15
16// Parse parses a natural language date string into a lunatask.Date.
17// Uses PHP strtotime syntax.
18//
19// Supported formats include:
20// - Relative words: "today", "tomorrow", "yesterday"
21// - Relative weekdays: "next Monday", "last Friday"
22// - Relative periods: "next week", "last month", "next year"
23// - Relative offsets: "+3 days", "-1 week", "3 days" (positive assumed)
24// - Compound expressions: "next Friday +2 weeks"
25// - Named dates: "March 5", "January 15 2024"
26// - ISO format: "2024-01-15"
27//
28// Returns today's date if the input is empty.
29func Parse(input string) (lunatask.Date, error) {
30 if input == "" {
31 return lunatask.Today(), nil
32 }
33
34 t, err := strtotime.StrToTime(input)
35 if err != nil {
36 return lunatask.Date{}, fmt.Errorf("parsing date %q: %w", input, err)
37 }
38
39 return lunatask.NewDate(t), nil
40}
41
42// ParseInTZ parses a natural language date string with timezone awareness.
43// The timezone affects interpretation of relative dates.
44func ParseInTZ(input string, tz *time.Location) (lunatask.Date, error) {
45 if input == "" {
46 return lunatask.Today(), nil
47 }
48
49 t, err := strtotime.StrToTime(input, strtotime.InTZ(tz))
50 if err != nil {
51 return lunatask.Date{}, fmt.Errorf("parsing date %q: %w", input, err)
52 }
53
54 return lunatask.NewDate(t), nil
55}