diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/soon/agenda.nim | 37 | ||||
| -rw-r--r-- | src/soon/parsetime.nim | 109 |
2 files changed, 80 insertions, 66 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 |
