aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhistoria <gravel.justness270@slmail.me>2024-08-17 06:51:36 -0400
committerhistoria <gravel.justness270@slmail.me>2024-08-17 06:51:36 -0400
commit5b3df42035f61474bbd21242acae3d2c780060a0 (patch)
tree8abac109b284e8155ad015a7ac6c5b35e1bb36f6
parenta31cf66d9400059752a2c480bac132960383a8d9 (diff)
downloadsoon-5b3df42035f61474bbd21242acae3d2c780060a0.tar.gz
fix: attachments with parsed times works
-rw-r--r--src/soon/agenda.nim37
-rw-r--r--src/soon/parsetime.nim109
-rw-r--r--tests/tparsetime.nim95
3 files changed, 129 insertions, 112 deletions
diff --git a/src/soon/agenda.nim b/src/soon/agenda.nim
index 59bbe12..49dcfe8 100644
--- a/src/soon/agenda.nim
+++ b/src/soon/agenda.nim
@@ -1,10 +1,14 @@
-import std/[times, strutils, strbasics, strscans, tables, algorithm, re]
+import std/[times, strutils, strbasics, strscans, tables, algorithm, re, oids]
import conditionchecker, typechecker, parsetime
type Event = tuple
name: string
time: DateTime
attachments: seq[string]
+ id: Oid
+
+proc allDay(): DateTime =
+ return parse("0000", "HHmm", utc())
# Splits a string on whitespace, but maintains whitespace in date groups
proc splitWhitespaceExceptParens(str:string): seq[string] =
@@ -43,15 +47,9 @@ proc allConditionsMet(conditions: Table[string,seq[string]], date: DateTime): bo
return false
return true
-#proc formatTime(time: string): DateTime =
-# let (start, end) = time.split("-", maxsplit = 1)
-# var matches: array[1, string]
-# discard find(condition, re"0?(\d{1,2})(:)?(\d{2})?([AaPp][Mm])?(\-(\d{1,2})(:)?(\d{2})?([AaPp][Mm])?)?", matches)
-
-
# Returns Table[event, attachments]
proc getEventsForDate(cal: seq[string], date: DateTime): seq[Event] =
- var lastInsertion = ""
+ var readyForComments = false
for line in cal:
var (success, dateConditions, event) = scanTuple(line, "$*,$*")
if success:
@@ -59,16 +57,20 @@ proc getEventsForDate(cal: seq[string], date: DateTime): seq[Event] =
let conditions = parseDateToTable(dateConditions)
if allConditionsMet(conditions, date):
event.strip
+ var newOid: Oid
if conditions.hasKey("time"):
- echo conditions["time"]
- #echo formatTime(conditions["time"])
- result.add((event, now(), @[]))
- lastInsertion = event
+ for t in conditions["time"]:
+ result.add((event, parsetime.toDateTime(t), @[], genOid()))
+ else:
+ result.add((event, allDay(), @[], genOid()))
+ readyForComments = true
+ else:
+ readyForComments = false
elif line.strip[0] == '+':
- if result[result.high].name == lastInsertion:
+ if result.len > 0 and readyForComments:
result[result.high].attachments.add(line)
elif line[0..1] == "- ":
- lastInsertion = ""
+ readyForComments = false
else:
echo "WARNING: Cannot parse line: ", line
@@ -83,7 +85,12 @@ proc printDaysEvents(cal: seq[string], date: DateTime, format: string) =
var events = getEventsForDate(cal, date)
if events.len > 0:
for event in events:
- echo date.format(format), " ", event.name
+ if event.time.monthday == 1:
+ # All day events
+ echo date.format(format), " ", event.name
+ else:
+ # Events with times
+ echo date.format(format), " ", event.time.format("HH:mm"), " ", event.name
for attachment in event.attachments:
let space = date.format(format).len + 2
echo attachment.indent(space)
diff --git a/src/soon/parsetime.nim b/src/soon/parsetime.nim
index 5cfa245..8819fc3 100644
--- a/src/soon/parsetime.nim
+++ b/src/soon/parsetime.nim
@@ -1,59 +1,66 @@
-import strutils, tables, re, times
-
-proc flipAmPm(s : string): string =
- case s
- of "am": return "pm"
- of "pm": return "am"
- else: return "am"
-
-proc fixTwelveAm(hour: int, meridiem: string): int =
- if hour == 12 and meridiem == "am":
- return 0
- if hour == 24:
- return 0
- return hour
-
-# Returns (hour, minute, meridium)
-proc parseString(t: string): (int, int, string) =
- var matches: array[3, string]
- discard find(t, re"^(\d{1,2}):?(\d{2})?([PpAa][Mm])?", matches)
- var
- hour = parseInt(matches[0])
- minute = 0
- meridiem = matches[2]
- if matches[1] != "": minute = parseInt(matches[1])
- hour = fixTwelveAm(hour, meridiem)
- if hour > 12:
- hour = hour - 12
- meridiem = "pm"
- return (hour, minute, meridiem)
-
-proc getMeridiem(startHour: int, startMin: int, endTime: string): string =
-# Determine meridium of the left hand side of a time range when it isn't specified
- var (endHour, endMinute, endMeridiem) = parseString(endTime)
- if (startHour < endHour and endHour == 12):
- return "am"
- if (startHour < endHour) or (startHour == endHour and startMin < endMinute):
- return endMeridiem
- elif startHour > endHour:
- return flipAmPm(endMeridiem)
+import strutils, re, times
+
+type
+ time = object
+ hour, min: int
+ meridiem: string
+ fmt: string
proc timeToStr(time: int): string =
result = intToStr(time)
if result.len == 1:
result = "0" & result
+proc toTwentyFourHourTime(t: time): time =
+ result = t
+ if t.meridiem == "pm" and t.hour != 12:
+ result.hour = t.hour + 12
+ if (t.meridiem == "am" and t.hour == 12) or result.hour == 24:
+ result.hour = 0
+ result.meridiem = ""
+ result.fmt = "24h"
+
+proc inferFullStartTime(startTime: time, endTime: time): time =
+# Infers startTime's 24h time based on known parameters of both times
+ var tfhStart = toTwentyFourHourTime(startTime)
+ var tfhEnd = toTwentyFourHourTime(endTime)
+ if startTime.fmt != "unknown" or endTime.fmt == "24h":
+ return tfhStart
+ if tfhStart.hour > tfhEnd.hour and tfhStart.hour - tfhEnd.hour <= 12:
+ tfhStart.hour = tfhStart.hour + 12
+ if tfhStart.hour == 24:
+ tfhStart.hour = 0
+ return tfhStart
+
+proc parseTime(s: string): time =
+ var matches: array[3, string]
+ discard find(s, re"^(\d{1,2}):?(\d{2})?([PpAa][Mm])?", matches)
+ result.hour = parseInt(matches[0])
+ result.min = 0
+ result.meridiem = matches[2]
+ if matches[1] != "":
+ result.min = parseInt(matches[1])
+
+proc getFormat(t: time): string =
+ if t.meridiem != "" and t.hour <= 12:
+ return "ampm"
+ elif t.hour > 12:
+ return "24h"
+ else:
+ return "unknown"
+
+proc makeTime(s: string): time =
+ result = parseTime(s)
+ result.fmt = getFormat(result)
+
proc toDateTime*(time: string): DateTime =
-# Returns a DateTime for any time string like 9am. 09:00, or 9-10pm
+# Returns a start DateTime for any time string like 9am. 09:00, or 9-10pm
let splitTime = time.split("-", maxsplit = 1)
- let startTime = splitTime[0]
- var (hour, minute, meridiem) = parseString(startTime)
- if meridiem == "" and splitTime.len > 1:
- meridiem = getMeridiem(hour, minute, splitTime[1])
- var sHour = timeToStr(hour)
- var sMin = timeToStr(minute)
- result = parse(sHour & sMin, "HHmm", utc())
- if meridiem == "pm" and hour <= 12:
- result = result + 12.hours
- if result.monthday == 2:
- result = result - 1.days
+ var startTime = makeTime(splitTime[0])
+ var endTime = startTime
+ if splitTime.len > 1:
+ endTime = makeTime(splitTime[1])
+ startTime = inferFullStartTime(startTime, endTime)
+ var strHour = timeToStr(startTime.hour)
+ var strMin = timeToStr(startTime.min)
+ result = parse(strHour & strMin, "HHmm", utc()) + 1.days
diff --git a/tests/tparsetime.nim b/tests/tparsetime.nim
index e49868c..d60a5fa 100644
--- a/tests/tparsetime.nim
+++ b/tests/tparsetime.nim
@@ -2,56 +2,59 @@ import soon/parsetime
import std/[unittest]
import std/[times]
+# Everything has +1.days to easily sort all-day events before scheduled ones
+
test "Parse single times":
- check toDateTime("9") == parse("0900", "HHmm", utc())
- check toDateTime("9am") == parse("0900", "HHmm", utc())
- check toDateTime("9:00") == parse("0900", "HHmm", utc())
- check toDateTime("9:30") == parse("0930", "HHmm", utc())
- check toDateTime("09:00") == parse("0900", "HHmm", utc())
- check toDateTime("09:30") == parse("0930", "HHmm", utc())
- check toDateTime("9:00am") == parse("0900", "HHmm", utc())
- check toDateTime("9:30pm") == parse("2130", "HHmm", utc())
- check toDateTime("09:00am") == parse("0900", "HHmm", utc())
- check toDateTime("09:00pm") == parse("2100", "HHmm", utc())
- check toDateTime("09:30am") == parse("0930", "HHmm", utc())
- check toDateTime("09:30pm") == parse("2130", "HHmm", utc())
- check toDateTime("17") == parse("1700", "HHmm", utc())
- check toDateTime("24") == parse("0000", "HHmm", utc())
- check toDateTime("17:00") == parse("1700", "HHmm", utc())
- check toDateTime("12:00") == parse("1200", "HHmm", utc())
- check toDateTime("24:00") == parse("0000", "HHmm", utc())
- check toDateTime("00:00") == parse("0000", "HHmm", utc())
- check toDateTime("01:00") == parse("0100", "HHmm", utc())
+ check toDateTime("9") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9am") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9:00") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9:30") == parse("0930", "HHmm", utc()) + 1.days
+ check toDateTime("09:00") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("09:30") == parse("0930", "HHmm", utc()) + 1.days
+ check toDateTime("9:00am") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9:30pm") == parse("2130", "HHmm", utc()) + 1.days
+ check toDateTime("09:00am") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("09:00pm") == parse("2100", "HHmm", utc()) + 1.days
+ check toDateTime("09:30am") == parse("0930", "HHmm", utc()) + 1.days
+ check toDateTime("09:30pm") == parse("2130", "HHmm", utc()) + 1.days
+ check toDateTime("17") == parse("1700", "HHmm", utc()) + 1.days
+ check toDateTime("24") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("17:00") == parse("1700", "HHmm", utc()) + 1.days
+ check toDateTime("12:00") == parse("1200", "HHmm", utc()) + 1.days
+ check toDateTime("24:00") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("00:00") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("01:00") == parse("0100", "HHmm", utc()) + 1.days
test "Parse time ranges":
- check toDateTime("9-1am") == parse("2100", "HHmm", utc())
- check toDateTime("9am-1am") == parse("0900", "HHmm", utc())
- check toDateTime("9:00-1:00am") == parse("2100", "HHmm", utc())
- check toDateTime("9:30-1:30am") == parse("2130", "HHmm", utc())
- check toDateTime("09:00-01:00am") == parse("2100", "HHmm", utc())
- check toDateTime("09:30-01:30am") == parse("2130", "HHmm", utc())
- check toDateTime("9:00am-1:00am") == parse("0900", "HHmm", utc())
- check toDateTime("9:30pm-01:00am") == parse("2130", "HHmm", utc())
- check toDateTime("09:00am-01:00am") == parse("0900", "HHmm", utc())
- check toDateTime("09:00pm-01:00am") == parse("2100", "HHmm", utc())
- check toDateTime("09:30am-01:30am") == parse("0930", "HHmm", utc())
- check toDateTime("09:30pm-01:30am") == parse("2130", "HHmm", utc())
- check toDateTime("17-1am") == parse("1700", "HHmm", utc())
- check toDateTime("17:00-1:00am") == parse("1700", "HHmm", utc())
- check toDateTime("12:00-1:00am") == parse("0000", "HHmm", utc())
- check toDateTime("12-1:00am") == parse("0000", "HHmm", utc())
- check toDateTime("00:00-01:00am") == parse("0000", "HHmm", utc())
- check toDateTime("11-12pm") == parse("1100", "HHmm", utc())
- check toDateTime("11-12am") == parse("2300", "HHmm", utc())
- check toDateTime("11-12") == parse("1100", "HHmm", utc())
- check toDateTime("9pm-12am") == parse("2100", "HHmm", utc())
- check toDateTime("11:00-13:00") == parse("1100", "HHmm", utc())
- check toDateTime("12:00-13:00") == parse("1200", "HHmm", utc())
- check toDateTime("11:00-24:00") == parse("1100", "HHmm", utc())
- check toDateTime("23:00-24:00") == parse("2300", "HHmm", utc())
- check toDateTime("24:00-23:00") == parse("0000", "HHmm", utc())
-
+ check toDateTime("9am-1am") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9:00am-1:00am") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9:30pm-01:00am") == parse("2130", "HHmm", utc()) + 1.days
+ check toDateTime("09:00am-01:00am") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("09:00pm-01:00am") == parse("2100", "HHmm", utc()) + 1.days
+ check toDateTime("09:30am-01:30am") == parse("0930", "HHmm", utc()) + 1.days
+ check toDateTime("09:30pm-01:30am") == parse("2130", "HHmm", utc()) + 1.days
+ check toDateTime("11:00-13:00") == parse("1100", "HHmm", utc()) + 1.days
+ check toDateTime("12:00-13:00") == parse("1200", "HHmm", utc()) + 1.days
+ check toDateTime("11:00-24:00") == parse("1100", "HHmm", utc()) + 1.days
+ check toDateTime("23:00-24:00") == parse("2300", "HHmm", utc()) + 1.days
+ check toDateTime("24:00-23:00") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("9pm-12am") == parse("2100", "HHmm", utc()) + 1.days
+ check toDateTime("17-1am") == parse("1700", "HHmm", utc()) + 1.days
+ check toDateTime("9-1am") == parse("2100", "HHmm", utc()) + 1.days
+ check toDateTime("9:00-1:00am") == parse("2100", "HHmm", utc()) + 1.days
+ check toDateTime("9:30-1:30am") == parse("2130", "HHmm", utc()) + 1.days
+ check toDateTime("09:00-01:00am") == parse("2100", "HHmm", utc()) + 1.days
+ check toDateTime("09:30-01:30am") == parse("2130", "HHmm", utc()) + 1.days
+ check toDateTime("17:00-1:00am") == parse("1700", "HHmm", utc()) + 1.days
+ check toDateTime("12:00-1:00am") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("12-1:00am") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("00:00-01:00am") == parse("0000", "HHmm", utc()) + 1.days
+ check toDateTime("11-12pm") == parse("1100", "HHmm", utc()) + 1.days
+ check toDateTime("11-12am") == parse("2300", "HHmm", utc()) + 1.days
+ check toDateTime("11-12") == parse("1100", "HHmm", utc()) + 1.days
+ check toDateTime("9-1700") == parse("0900", "HHmm", utc()) + 1.days
+ check toDateTime("9-1100") == parse("0900", "HHmm", utc()) + 1.days