timewarrior/doc/notes.txt
2015-12-09 09:04:44 -05:00

325 lines
14 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Timewarrior
===========
Tracking time is complex, and requires more than simply a set of start/stop
timestamps. There are daily schedules, breaks, meetings, holidays, and
vacations to consider.
For a tool to be useful, it must support all the above, and make the task of
tracking time simple.
Goals
-----
Provide a personal tool to easily track time spent and generate status reports
in multiple formats and styles. The tool will "do the right thing" as much as
possible. Tool will be Open Source.
Non-Goals
---------
- No cloud support.
- No multi-user support.
- No sync support.
- No precision higher than a minute.
Integration
-----------
- As a sister-product to Taskwarrior and Tasksh, integration should be as
simple as installing a hook script.
- Software may invoke timew for tracking, but timew will not invoke any other
software.
- An export and import feature, using JSON, will allow further integration.
Definitions
-----------
- A timeline is a continuum that is the one-dimensional space that timestamps
and intervals map onto.
- A timmestamp is a point on a timeline.
- An interval is a span of time on a timeline, consisting of two timestamps.
- A tag is an arbitrary string.
- An interval may have any number of tags.
- An timestamp may have any number of tags.
- An interval may be an inclusion or an exclusion. A weekend is an exclusion,
time spent working is an inclusion.
- A workweek is defined by time that is not spent working, it is a set of
excluded intervals. Those intervals are tagged to be easily identifiable.
- Lunch could be an inclusion, but tagged as non-work. It could also be an
exclusion.
- An interval set is a set of tags that, when queried, results in the desired
subset of all intervals. For example, 'home' and 'painting' are tags that
represent all the tracked time with those tags. The interval set may be the
empty set.
- The time resolution is 1 minute.
Rule System Use Cases
---------------------
A rule system should be able to evaluate conditions and perform actions, which
include continuing to process rules, or stopping. The conditions will need to
access configuration, exclusions, and tracking data.
- A constraint on total tracking time, "do not spend more than 4 hours on x".
- A constraint that only allows certain tags to be used together, to prevent
client 1 from being billed for project 2.
- A constraint that only allows multiples of 15-minute intervals.
Ref: http://martinfowler.com/bliki/RulesEngine.html
Example rules (assuming Python-like syntax):
define rule workweek:
holidays eng-USA
workweek mon,tue,wed,thu,fri
workday start 510
workday end 1050
workday tue end 900
define rule my_rule:
total_hours = sum_week +tag1
if total_hours > 12:
fail "The 'tag1' tag cannot exceed 12 hours/wk"
(needs work)
CLI Syntax
----------
The CLI shall have a well-defined and unambiguous grammar.
As timew will use tags, by default we assume the same convention as Taskwarrior,
namely:
+tag Implies the presence of a tag
-tag Implies the absence of a tag
Timestamp values should support a wide range of unambiguous formats, including:
today
9am
today 9am
0900
9:00
2015-12-02T09:00
2nd 4pm
Interval values should support a wide range of unambiguous formats, including:
<timestamp> - <timestamp>
<timestamp> to <timestamp>
from <timestamp> to <timestamp>
until <timestamp>
from <timestamp>
<timestamp> for <duration>
Macros
------
A macro is a keyword that can take arguments, and expands to a set of one or
more other timew commands, with some dynamic aspect. For example, the macro
named 'staff meeting' could be an interval that is on Wednesdays at 10:00, and
has a set of associated tags. This would then create an appropriately tagged
interval.
General Use Cases
-----------------
Suppose 'today' is 2015-11-24, a Tuesday at noon. This date is chosen because
it is mid-week, a holiday is coming up, and workday exceptions are typical.
Here is the timeline, with the successive exclusions added, as a work week is
defined:
2015
November December
W48 W49
23rd 24th 25th 26th 27th 28th 29th 30th 1st
Monday Tuesday Wednesday Thursday Friday Saturday Sunday Monday Tuesday
: : : : : : : : : :
:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:
0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0
|
| ------------ $ timew holidays eng-USA
| ------------------------ $ timew define workweek mon-fri
---- ---- | ---- ---- ---- ---- ---- ---- ---- $ timew define workday start 8:30am
--- | --- --- --- --- --- --- --- --- $ timew define workday end 1730
| ---- $ timew define workday tue end 3pm
|
+++++ ++++ +++++ +++++ +++++ +++++ Resulting work week
|
now
On that same timeline, here are some example tracked intervals:
|
+++++ tag1 tag2 $ timew track +tag1 +tag2 yesterday
++++ tag1 tag2 $ timew track +tag1 +tag2 today
+ tag1 tag2 $ timew start +tag1 +tag2
+++ tag1 tag2 $ timew start +tag1 +tag2 backfill
+ tag3 $ timew track +tag3 yesterday 2pm - 4pm
+ tag4 $ timew track -tag3 +tag4 yesterday 2pm - 4pm
|
|
now
Here is the example data storage for the above workweek:
define rule workweek:
holidays eng-USA
workweek mon,tue,wed,thu,fri
workday start 510
workday end 1050
workday tue end 900
Time tracking is based on the inclusion intervals derived from the above rule.
For week 48 those would be:
2015-11-23 510-1050
2015-11-24 510-900
2015-11-25 510-1050
2015-11-27 510-1050
Given these intervals, tracking becomes a set of basic modifications:
The date 'yesterday' refers to the whole day, and overrides any other
intervals:
$ timew track +tag1 +tag2 yesterday
--> 'yesterday' resolves to 2015-11-23
--> delete all intervals for 2015-11-23
--> obtain inclusions for 2015-11-23: 510-1050
--> store: 2015-11-23 510-1050 tag1 tag2
The date 'today' refers to the whole day, and overrides any other intervals:
$ timew track +tag1 +tag2 today
--> 'today' resolves to 2015-11-24
--> delete all intervals for 2015-11-24
--> obtain inclusions for 2015-11-24: 510-900
--> store: 2015-11-24 510-900 tag1 tag2
The 'start' command uses 'now' (12:00pm) in this alternate example:
$ timew start +tag1 +tag2
--> 'now' resolves to 2015-11-24T12:00
--> obtain inclusions for 2015-11-24: 510-900
--> store: 2015-11-24 720- tag1 tag2
Note the open-ended interval
The 'start' recognizes 'backfill' to indicate that earlier, untracked
inclusions should be tracked:
$ timew start +tag1 +tag2 backfill
--> 'now' resolves to 2015-11-24T12:00
--> obtain inclusions for 2015-11-24: 510-900
--> store: 2015-11-24 510- tag1 tag2
Note the open-ended, back-dated interval
Inserting tracked time into an existing set of intervals:
$ timew track +tag3 yesterday 2pm - 4pm
--> 'yesterday' resolves to 2015-11-23
--> '2pm' - '4pm' resolves to 840-960
--> obtain inclusions for 2015-11-23: 510-1050
--> store: 2015-11-23 840-960 tag3
Change tagging for an interval:
$ timew track -tag3 +tag4 yesterday 2pm - 4pm
TBD
Not shown:
- $ timew holidays work 2015-11-26 # override the holiday
Data Format
-----------
- The storage format should be all text files.
- An example storage format for a work week:
-
- An example storage format as a starting point, in compact form. First line is
a full day, no break from 8am - 5pm. Second line is the same with an untracked
lunch break:
2015-12-01 480-1020 tag1 tag2
2015-12-02 480-720 tag1 tag2, 780-1020 tag1 tag2
- Same in JSON:
[
{"day":"2015-12-01","intervals":[{"start":480,"end":1020,"tags":["tag1","tag2"]}]}
{"day":"2015-12-02","intervals":[{"start":480,"end":720,"tags":["tag1","tag2"]},{"start":780,"end":1020,"tags":["tag1","tag2"]]}
]
- If the user runs "timew track tag1 tag2 yesterday", then the "yesterday" is
resolved against the set of exclusions to determine its boundaries, and record
as a set of matching intervals. A later change to the work start time will
not be reflected in already tracked time.
- Tags may need to be quoted, to allow spaces.
Reporting
---------
- Reports should have multiple output formats: TTY, JSON, HTML.
-
Unsolved Issues
---------------
- Is a tag a single word, or a KV pair? Why? If tags are quoted strings, then
there will be no issues with folks wanting to use actual project names.
- Multiple timelines?
- Terminology for backwards and forwards tracking (backfill for the past, and
just assume everythign else is for the future)?
- Given this:
$ timew track yesterday 9am - 5pm tag1
What does this do:
$ timew track yesterday 10am - 11am tag2
Does it yield:
a) yesterday 540-1020 tag, 600-660 tag2 # overlap
b) yesterday 540-600 tag1, 600-660 tag2, 660-1020 tag1 # no overlap
c) yesterday 540-600 tag1, 600-660 tag1 tag2, 660-1020 tag1 # explicit overlap
Stating 'track yesterday 10am - 11am tag2' sounds imperative, thus overriding
any existing tags in that interval. Perhaps a 'merge' keyword could be added
to combined the results (track yesterday 10am - 11am tag2 merge)?
Raw Notes (Slack)
-----------------
F: start (frontfill) and backfill (end) could be considered orthogonal to each other. They just operate into different directions. but I think they behave the same, more or less.
F: Which brings me to the topic of overlapping intervals. While most of things would not be multitasking/overlapping. I could think of a few things that could be reported overlapping.
P: Agreed, I can multitask and be pursuing two results at the same time.
P: I can do all these [manipulations] with my finger. But not at the CLI. That means lists, and ID numbers, I think. Any thoughts?
F: List… Hm. Dont we already have one implicitly with the timeline and timestamps?
P: Yes, but youd need to view it, in order to identify which block should be manipulated.
F: Cant that list not be a list of key/value pairs? The keys are the minutes of the day, the values the different tags (another list of key/values).
F: Then you just traverse the minutes in either direction.
F: If you want to extend an event just look at the minutes after it and change the stored tags...
P: You said earlier about time points, like monitoring systems. If I jsut drop a point at 8:55, then it could merge it with the 9:00 point because the tags match.
F: OTOH the command at 9:50 could also mean that the first block should go from 8:55 to 9:40. It was originally 45 minutes long. Should it now also be 45 minutes. Or do you want to extend it with 5mins from 8:55 to 9:45?
P: Your question above: should we move the block intact, or stretch it? I think thats an important flexibility we need. so both.
F: I am thinking if that list would need to contain 1440 entries or if it could be smaller.
F: Or if we just store less elements in it from the beginning and then just populate them as we add events to the day.
F: If the list is fully populated then querying and reporting is just traversing and adding per resolution. No fancy time calculations.
F: Just count how many minute entries you have for a tag combination.
F: Would that be slow for a week or month?
P: So initially we define our work week, which to me involves about 8 blocks of time, which is just 16 time points. So thats nothing.
P: Well, I can represent an array of 1440 slots very efficiently: 1-1440 tag1
P: Then you add a block, and it gets bisected: 1-300 tag1, 301-800 tag2, 801-1440 tag1
F: Exactly.
P: So with 10 separately billable chunks of time recorded, there would be 11 blocks, and the 8 that define the week. Trivial.
F: And their length is y-x.
P: Even easier then: 1 tag1, 301 tag2, 801 tag1
--