749 lines
22 KiB
ReStructuredText
749 lines
22 KiB
ReStructuredText
Tiempo
|
|
======
|
|
|
|
Synopsys
|
|
--------
|
|
|
|
``t -h|--help``
|
|
|
|
``t help SUBCOMMAND``
|
|
|
|
``t SUBCOMMAND -h|--help``
|
|
|
|
``t SUBCOMMAND [OPTIONS]``
|
|
|
|
Subcommands
|
|
-----------
|
|
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| Command | Alias | Description |
|
|
+===========+=======+==========================================================+
|
|
| archive | a | Archive entries to a hidden timesheet. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| backend | b | Open an sqlite shell to the database (requires having |
|
|
| | | sqlite3 installed. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| configure | c | Configure tiempo in-place or get path to config file. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| display | d | Display all entries in the current sheet. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| edit | e | Edit an entry. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| in | i | Start an entry in the current timesheet. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| kill | k | Delete an entry or an entire timesheet. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| list | l | List existing sheets. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| month | m | Display entries starting this month. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| now | n | Show all running entries. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| out | o | End the active entry in the current timesheet. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| resume | r | Restart the timer for an entry. Defaults to the last |
|
|
| | | active entry. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| sheet | s | Switch to a new or existing timesheet. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| today | t | Display entries that started today. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| week | w | Display entries starting last monday or later (First day |
|
|
| | | of the week configurable). |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
| yesterday | y | Display entries that started yesterday. |
|
|
+-----------+-------+----------------------------------------------------------+
|
|
|
|
Description
|
|
-----------
|
|
|
|
Tiempo is a command-line time tracker. Register the start and end times of your
|
|
activities and get results by day, week, month or custom periods of time in
|
|
different formats, including custom ones.
|
|
|
|
Entries are optionally organized in timesheets which you can use to represent
|
|
projects, clients etc. Most commands (notably the ones that display entries)
|
|
work on the *current* or *active* timesheet.
|
|
|
|
The entries are stored in a local Sqlite3 database whose location you can learn
|
|
by looking at your config file (whose location you can learn running ``t c``).
|
|
|
|
**tiempo** stores entries as UTC and then converts to the local timezone for
|
|
displaying and querying. This means that even if you change timezones your
|
|
recorded times will be correct, although their displayed results might vary if
|
|
grouping by day for example.
|
|
|
|
This tool is compatible with a previous one with the same purpose called
|
|
``timetrap``. The most notable difference being that timetrap stores times as
|
|
local timezone times, which makes it messy if you switch timezones. Another
|
|
difference is that in timetrap you used the internal ruby API to add custom
|
|
display formats and in ``tiempo`` you'll use standard input/output and
|
|
command-line arguments in any language of your choice.
|
|
|
|
Tutorial
|
|
--------
|
|
|
|
.. note::
|
|
|
|
yo, doc this
|
|
|
|
Subcommands
|
|
-----------
|
|
|
|
.. _t-archive:
|
|
|
|
t-archive
|
|
.........
|
|
|
|
``t a|archive [OPTIONS] [SHEET]``
|
|
|
|
To archive means to move entries from the current or specified timesheet to a
|
|
different "hidden" sheet so that when you query the current sheet you don't see
|
|
them but they are kept in the database. Archived entries are stored in a sheet
|
|
with the same name of the original with an underscore as prefix. Use
|
|
:ref:`t-list` to see archived sheets.
|
|
|
|
By default this command will ask for you confirmation, then archive ALL entries
|
|
in the current timesheet. Pass ``--fake`` to only display the entries using the
|
|
``text`` formatter (useful if you want to make sure that the archived
|
|
time/entries are correct).
|
|
|
|
Using ``--start`` and ``--end`` you can further limit the period of time that
|
|
will be archived (See :ref:`specifying-times` section of the docs on the
|
|
accepted formats). You can use ``--grep`` to only archive certain entries that
|
|
match the given regular expression.
|
|
|
|
If what you need is to archive a specific elapsed time, for example only 15
|
|
hours out of however many the timesheet has use ``--time`` with the amount of
|
|
hours you want to archive.
|
|
|
|
**Options**
|
|
|
|
-f, --fake
|
|
Don't actually archive the entries, just display them
|
|
|
|
-e, --end <TIME>
|
|
Include entries that start on this date or earlier
|
|
|
|
-g, --grep <REGEXP>
|
|
Include entries where the note matches this regexp.
|
|
|
|
-s, --start <TIME>
|
|
Include entries that start on this date or later
|
|
|
|
-t, --time <HOURS>
|
|
Time in hours to archive. Archived time will be equal or less than this.
|
|
|
|
``SHEET``
|
|
Archive entries from this timesheet instead of the current one.
|
|
|
|
t-backend
|
|
.........
|
|
|
|
``t b|backend``
|
|
|
|
Open a sqlite3 shell into the database. Sqlite3 must be installed and in the
|
|
``PATH`` variable for this command to work.
|
|
|
|
.. _t-configure:
|
|
|
|
t-configure
|
|
...........
|
|
|
|
``t c|configure [OPTIONS]``
|
|
|
|
If called without arguments ``t c`` will print the absoulte path to the config
|
|
file. If you pass arguments they'll be used to edit your config file in place.
|
|
|
|
.. warning::
|
|
|
|
This will erase any comments you might have added to your toml or yaml file.
|
|
It is better to edit the config file manually with your preferred text
|
|
editor:
|
|
|
|
.. code:: shell-session
|
|
|
|
vim $(t c)
|
|
|
|
**Options**
|
|
|
|
--auto-checkout
|
|
Checkout of current running entry when starting a new one. **Not
|
|
implemented**.
|
|
|
|
--no-auto-checkout
|
|
Starting a new entry fails if one is running (default).
|
|
|
|
--no-require-note
|
|
Entries can be created without a note.
|
|
|
|
--require-note
|
|
Prompt for a note if one isn't provided when checking in (default).
|
|
|
|
--append-notes-delimiter <DELIMITER>
|
|
delimiter used when appending notes via t edit --append. Default: ' '
|
|
(space).
|
|
|
|
--database-file <PATH>
|
|
Set the absoulte path to the sqlite database. A new database will be created
|
|
at this location if one does not exist.
|
|
|
|
--default-formatter <FORMATTER>
|
|
The format to use when display commands are invoked without a ``--format``
|
|
option. Defaults to ``'text'``. See :ref:`settings` section of the docs for
|
|
per-command default formatter.
|
|
|
|
``--formatter-search-paths <PATH>[,<PATH>...]``
|
|
comma separated paths to search for user defined fomatters. See
|
|
:ref:`custom-formatters` section for more info on this.
|
|
|
|
--interactive-entries <N>
|
|
How many unique previous notes to show when selecting interactively. An
|
|
example of an interactive command is ``t resume -i``.
|
|
|
|
--note-editor <EDITOR>
|
|
Specify a custom command used to edit an entry's note. Default: $EDITOR
|
|
|
|
--round-in-seconds <SECONDS>
|
|
The duration of time to use for rounding with the -r flag. Default: 900 (15
|
|
m). **Not implemented**.
|
|
|
|
--week-start <DAY>
|
|
The day of the week to use as the start of the week for t week. Default:
|
|
monday [possible values: monday, tuesday, wednesday, thursday, friday,
|
|
saturday, sunday]
|
|
|
|
.. _t-display:
|
|
|
|
t-display
|
|
.........
|
|
|
|
``t d|display [OPTIONS] [SHEET|all|full]``
|
|
|
|
Display all entries in the current timesheet using the specified formatter (by
|
|
default this is ``text``). For more information on formatters see
|
|
:ref:`default-formatters`. For information on custom formatters see
|
|
:ref:`custom-formatters`.
|
|
|
|
It is worh noting that **BOTH** the ``--start`` and ``--end`` arguments act on
|
|
the start time of the entry.
|
|
|
|
**Options**
|
|
|
|
-v, --ids
|
|
Print database ids (for use with edit).
|
|
|
|
-e, --end <TIME>
|
|
Include entries that start on this date or earlier.
|
|
|
|
-f, --format <FORMAT>
|
|
The output format. Valid built-in formats are chart, text, ical, csv, json
|
|
and ids. See :ref:`default-formatters` for more info. See
|
|
:ref:`custom-formatters` to learn how to make your own.
|
|
|
|
-g, --grep <REGEXP>
|
|
Only display entries whose notes match this regular expression.
|
|
|
|
-s, --start <TIME>
|
|
Include entries that start on this date or later.
|
|
|
|
``<SHEET>``
|
|
The sheet to display. Pass 'all' to see entries from all sheets or 'full' to
|
|
see hidden entries.
|
|
|
|
t-edit
|
|
......
|
|
|
|
``t e|edit [OPTIONS] [NOTE]``
|
|
|
|
If run without arguments this command will launch a text editor with the text of
|
|
the current timesheet's last entry's note. Upon saving and exiting the new text
|
|
will be set. If a string is given as command-line argument it will be used as
|
|
the new note and no editor will be launched. If used with ``--append`` the
|
|
new text will be appended to the previous one using whatever string is set as
|
|
:ref:`append_notes_delimiter` in the settings file.
|
|
|
|
The last entry is defined as the one that was started last, not necessarily the
|
|
one with the highest ID in the current timesheet.
|
|
|
|
You can also leave the note untouched and edit other parts of the entry like its
|
|
start and end times using ``--start`` and ``--end`` respectively, see
|
|
:ref:`specifying-times`. Or you can move an entry that was created in the wrong
|
|
timesheet by using ``--move``.
|
|
|
|
**Options**
|
|
|
|
-z, --append
|
|
Append the new text to the current note instead of replacing it.
|
|
|
|
-e, --end <TIME>
|
|
Set this as the end time.
|
|
|
|
--id <ID>
|
|
Edit entry with this ID instead of the last one in the current sheet.
|
|
|
|
-m, --move <SHEET>
|
|
Move entry to another sheet.
|
|
|
|
-s, --start <TIME>
|
|
Set this as the start time.
|
|
|
|
``<NOTE>``
|
|
Set this as the entry's note. It will replace the previous one unless
|
|
``--append`` is given.
|
|
|
|
t-help
|
|
......
|
|
|
|
``t help SUBCOMMAND``
|
|
|
|
Get help on the specified subcommand. It is equivalent to passing ``-h`` to any
|
|
subcommand.
|
|
|
|
t-in
|
|
....
|
|
|
|
``t i|in [--at TIME] [NOTE]``
|
|
|
|
Start an entry in the current timesheet. If used without arguments and
|
|
:ref:`require_note` is set to ``true`` in the settings then it will launch a
|
|
text editor for you to write a note. Pass ``--at`` to set a specific time of
|
|
start instead of now, like in case you forgot to start an activity five minutes
|
|
ago:
|
|
|
|
.. code:: shell-session
|
|
|
|
t i --at '5 min ago' 'writing the codez'
|
|
|
|
t-kill
|
|
......
|
|
|
|
``t k|kill (--id ID|--last|SHEET)``
|
|
|
|
Use this to completely delete entries. Pass a timesheet name to delete all
|
|
entries from it or use ``--id`` to delete an entry by its ID. IDs from entries
|
|
can be shown passing ``-v`` to the 'display' family of subcommands. To delete
|
|
only the last entry from the sheet pass ``--last`` as single argument.
|
|
|
|
This command will ask for confirmation before touching the database.
|
|
|
|
If you'd prefer to keep record of entries but have them out of the way use
|
|
:ref:`t-archive`.
|
|
|
|
**Options**
|
|
|
|
-l, --last
|
|
Delete the last entry of the current sheet
|
|
|
|
--id <ID>
|
|
Delete entry with this ID instead of sheet
|
|
|
|
``<SHEET>``
|
|
Delete an entire sheet by its name
|
|
|
|
.. _t-list:
|
|
|
|
t-list
|
|
......
|
|
|
|
``t l|list [-a|--all]``
|
|
|
|
Lists existing timesheets. Pass ``--all`` to also list hidden (archived) ones.
|
|
The output includes 4 columns: the name of the timesheet, the elapsed time of
|
|
the running entry, the accumulated time for the day and the total time (sum of
|
|
all entries per timesheet).
|
|
|
|
.. code:: text
|
|
|
|
Timesheet Running Today Total Time
|
|
|
|
default 0:00:00 0:00:00 2:39:38
|
|
- foo 0:00:00 0:30:01 0:30:01
|
|
* pink 0:00:00 0:05:04 0:05:04
|
|
--------------------------------------------
|
|
0:00:00 0:35:06 3:14:44
|
|
|
|
An asterisk (*) at the left will indicate the current timesheet and a dash (-)
|
|
indicates the previously used one. This is relevant for :ref:`t-sheet` where you
|
|
can use - as the timesheet name to just switch to the previous one.
|
|
|
|
t-month
|
|
.......
|
|
|
|
``t m|month [OPTIONS] [SHEET|all|full]``
|
|
|
|
Like :ref:`t-display` but only display entries that started this month in the
|
|
current timezone. Pass ``--month MONTH`` to display entries of different months.
|
|
|
|
Just like ``t-display`` this accepts ``--grep``, ``--ids``, and ``--format``.
|
|
|
|
t-now
|
|
.....
|
|
|
|
``t n|now``
|
|
|
|
Show only timesheets with running entries. Since every timesheet can only have
|
|
one running entry at a time this command displays its note.
|
|
|
|
.. code:: text
|
|
|
|
Timesheet Running Activity
|
|
|
|
* default 0:00:01 reading
|
|
- pink 0:00:21 gardening
|
|
|
|
Just like :ref:`t-list` it displays an asterisk for the current timesheet and a
|
|
dash for the previous one.
|
|
|
|
t-out
|
|
.....
|
|
|
|
t-resume
|
|
........
|
|
|
|
.. _t-sheet:
|
|
|
|
t-sheet
|
|
.......
|
|
|
|
t-today
|
|
.......
|
|
|
|
``t t|today [OPTIONS] [SHEET|all|full]``
|
|
|
|
Like :ref:`t-display` but only display entries that started today in the current
|
|
timezone. Pass ``--end`` to further filter entries that started earlier than the
|
|
given time.
|
|
|
|
Just like ``t-display`` this accepts ``--grep``, ``--ids``, and ``--format``.
|
|
|
|
t-week
|
|
......
|
|
|
|
``t w|week [OPTIONS] [SHEET|all|full]``
|
|
|
|
Like :ref:`t-display` but only display entries that started this week in the
|
|
computer's timezone. The first day of the week by default is ``monday`` but this
|
|
is configurable. See :ref:`settings` and :ref:`t-configure`.
|
|
|
|
Just like ``t-display`` this accepts ``--grep``, ``--ids``, and ``--format``.
|
|
|
|
t-yesterday
|
|
...........
|
|
|
|
``t y|yesterday [OPTIONS] [SHEET|all|full]``
|
|
|
|
Like :ref:`t-display` but only display entries that started yesterday in the
|
|
computer's current timezone.
|
|
|
|
Just like ``t-display`` this accepts ``--grep``, ``--ids``, and ``--format``.
|
|
|
|
.. _settings:
|
|
|
|
Settings
|
|
--------
|
|
|
|
.. note::
|
|
|
|
describe the settings file
|
|
|
|
.. _append_notes_delimiter:
|
|
|
|
append_notes_delimiter
|
|
......................
|
|
|
|
.. _require_note:
|
|
|
|
require_note
|
|
............
|
|
|
|
Per command default formatters
|
|
..............................
|
|
|
|
.. note::
|
|
|
|
likely move this to the section above
|
|
|
|
**New in 1.4.0**
|
|
|
|
It might be the case that you want to use one default formatter for when you use
|
|
``t week`` and a different one for ``t month`` or ``t today``. That's what
|
|
per-command default formatters are for. To use them just add a ``commands``
|
|
section to your config file and set ``default_formatter`` on some formatters.
|
|
This is what it would look like:
|
|
|
|
**In toml**
|
|
|
|
.. code:: toml
|
|
|
|
[commands.week]
|
|
default_formatter = "chart"
|
|
|
|
[commands.month]
|
|
default_formatter = "ical"
|
|
|
|
**In yaml**
|
|
|
|
.. code:: yaml
|
|
|
|
commands:
|
|
week:
|
|
default_formatter: chart
|
|
month:
|
|
default_formatter: ical
|
|
|
|
Files and paths
|
|
---------------
|
|
|
|
.. note::
|
|
|
|
explain the config file, database path and environment variables
|
|
|
|
.. _specifying-times:
|
|
|
|
Specifying times
|
|
----------------
|
|
|
|
Some arguments accept a time as value, like ``t in``'s ``--at`` or ``t d
|
|
--start``. These are the accepted formats:
|
|
|
|
**Something similar to ISO format** will be parsed as a time in the computer's
|
|
timezone.
|
|
|
|
* ``2021-01-13`` a date
|
|
* ``2019-05-03 11:13`` a date with portions of a time
|
|
|
|
**ISO format with offset or UTC** will be parsed as a time in the specified
|
|
timezone. Use ``Z`` for ``UTC`` and an offset for everything else
|
|
|
|
* ``2021-01-13Z``
|
|
* ``2005-10-14 19:20:35+05:00``
|
|
|
|
**something that looks like an hour** will be parsed as a time in the current
|
|
day in the computer's timezone. Add ``Z`` or an offset to specify the timezone.
|
|
|
|
* ``11:30``
|
|
* ``23:50:45`` (with seconds)
|
|
|
|
**some human times**, for now restricted to time ago:
|
|
|
|
* ``an hour ago``
|
|
* ``a minute ago``
|
|
* ``50 min ago``
|
|
* ``1h30m ago``
|
|
* ``two hours thirty minutes ago``
|
|
|
|
.. _default-formatters:
|
|
|
|
Default formatters
|
|
------------------
|
|
|
|
Tiempo comes with a handful of formatters that display your entries in different
|
|
ways. Here's the full list.
|
|
|
|
chart
|
|
.....
|
|
|
|
(New in 1.4.0) Displays a nice chart of the weekly progress:
|
|
|
|
.. code:: text
|
|
|
|
Date Day Chart Hours
|
|
|
|
Sep 5 Mon ####### 3.8
|
|
6 Tue #### 2.3
|
|
7 Wed ####### 3.9
|
|
8 Thu 0.0
|
|
9 Fri ######### 4.5
|
|
10 Sat ######### 4.7
|
|
11 Sun 0.0
|
|
|
|
Week 19.3/20.0
|
|
|
|
**Settings**
|
|
|
|
By default this formatter will only display a nice chart of the progress divided
|
|
by week and respecting the ``week_start`` setting. However you may specify a
|
|
daily goal and a weekly goal to customize the chart, as well as how many minutes
|
|
each character represents:
|
|
|
|
In toml:
|
|
|
|
.. code:: toml
|
|
|
|
[formatters.chart]
|
|
daily_goal_hours = 4
|
|
weekly_goal_hours = 20
|
|
character_equals_minutes = 30
|
|
|
|
In yaml:
|
|
|
|
.. code:: yaml
|
|
|
|
formatters:
|
|
chart:
|
|
daily_goal_hours: 4
|
|
weekly_goal_hours: 20
|
|
character_equals_minutes: 30
|
|
|
|
text
|
|
....
|
|
|
|
Displays nicely the entries grouped by sheet and day. This is the default
|
|
formatter. Pass ``-v`` to also reveal each entry's id:
|
|
|
|
.. code:: text
|
|
|
|
Timesheet: foo
|
|
Day Start End Duration Notes
|
|
Tue Sep 20, 2022 09:09:58 - 09:40:13 0:30:15 write tiempo's docs
|
|
09:41:01 - 10:11:20 0:30:18 work on pizarra.categulario.xyz
|
|
1:00:34
|
|
-------------------------------------------------------------------------------------
|
|
Total 1:00:34
|
|
|
|
ical
|
|
....
|
|
|
|
This formatter's output can be redirected to a file and then uploaded to a
|
|
calendar app:
|
|
|
|
.. code:: text
|
|
|
|
BEGIN:VCALENDAR
|
|
CALSCALE:GREGORIAN
|
|
METHOD:PUBLISH
|
|
PRODID:tiempo-rs
|
|
VERSION:2.0
|
|
BEGIN:VEVENT
|
|
DESCRIPTION:write tiempo's docs
|
|
DTEND:20220920T134013Z
|
|
DTSTAMP:20220920T130958Z
|
|
DTSTART:20220920T130958Z
|
|
SEQUENCE:0
|
|
SUMMARY:write tiempo's docs
|
|
UID:tiempo-10@abraham-lenovo-t470s
|
|
END:VEVENT
|
|
BEGIN:VEVENT
|
|
DESCRIPTION:work on pizarra.categulario.xyz
|
|
DTEND:20220920T141120Z
|
|
DTSTAMP:20220920T134101Z
|
|
DTSTART:20220920T134101Z
|
|
SEQUENCE:0
|
|
SUMMARY:work on pizarra.categulario.xyz
|
|
UID:tiempo-11@abraham-lenovo-t470s
|
|
END:VEVENT
|
|
END:VCALENDAR
|
|
|
|
csv
|
|
...
|
|
|
|
Dump the entries as CSV to stdout. Useful for passing entries to a different
|
|
tool. Pass ``-v`` to add an ``id`` column.
|
|
|
|
.. code:: text
|
|
|
|
start,end,note,sheet
|
|
2022-09-20T13:09:58.805280Z,2022-09-20T13:40:13.837994Z,write tiempo's docs,foo
|
|
2022-09-20T13:41:01.478854Z,2022-09-20T14:11:20.461322Z,work on pizarra.categulario.xyz,foo
|
|
|
|
json
|
|
....
|
|
|
|
Dump the entries in JSON format:
|
|
|
|
.. code:: json
|
|
|
|
[{"id":10,"note":"write tiempo's docs","start":"2022-09-20T13:09:58.805280283Z","end":"2022-09-20T13:40:13.837994932Z","sheet":"foo"},{"id":11,"note":"work on pizarra.categulario.xyz","start":"2022-09-20T13:41:01.478854071Z","end":"2022-09-20T14:11:20.461322041Z","sheet":"foo"}]
|
|
|
|
ids
|
|
...
|
|
|
|
Dump only the ids in a single line:
|
|
|
|
.. code:: text
|
|
|
|
2196 2197 2198 2199 2200 2201
|
|
|
|
.. _custom-formatters:
|
|
|
|
Custom formatters
|
|
-----------------
|
|
|
|
You can implement your own formatters for all subcommands that display entries
|
|
(like ``t display``, ``t week`` etc.). It is as easy as creating an executable
|
|
file written in any programming language (interpreted or compiled) and placing
|
|
it in a path listed in the config value for ``formatter_search_paths``.
|
|
|
|
This executable will be given as standard input a csv stream with each row
|
|
representing a time entry with the same structure as the ``csv`` formatter
|
|
output. It will also be given a command line argument representing user settings
|
|
for this formatter stored in the config file and formatted as JSON.
|
|
|
|
Example
|
|
.......
|
|
|
|
Suppose we have this config file:
|
|
|
|
.. code:: toml
|
|
|
|
database_file = "/home/user/.config/tiempo/database.sqlite3"
|
|
round_in_seconds = 900
|
|
append_notes_delimiter = " "
|
|
formatter_search_paths = ["/home/user/.config/tiempo/formatters"]
|
|
default_formatter = "text"
|
|
auto_sheet = "dotfiles"
|
|
auto_sheet_search_paths = ["/home/user/.config/tiempo/auto_sheets"]
|
|
auto_checkout = false
|
|
require_note = true
|
|
week_start = "Monday"
|
|
|
|
[formatters.earnings]
|
|
hourly_rate = 300
|
|
currency = "USD"
|
|
|
|
then we can create the ``earnings`` formatter by placing the following file in
|
|
``/home/user/.config/tiempo/formatters/earnings`` and making it executable:
|
|
|
|
.. code:: python
|
|
|
|
#!/usr/bin/env python3
|
|
import sys, json, csv
|
|
from datetime import datetime, timezone, timedelta
|
|
from math import ceil
|
|
|
|
# Settings for this formatter passed as the first argument
|
|
config = json.loads(sys.argv[1])
|
|
|
|
reader = csv.DictReader(
|
|
sys.stdin, # entries are received from stdin
|
|
fieldnames=['id', 'start', 'end', 'note', 'sheet'],
|
|
)
|
|
|
|
total = timedelta(seconds=0)
|
|
|
|
for line in reader:
|
|
# times are formatted as ISO format
|
|
start = datetime.strptime(line['start'], '%Y-%m-%dT%H:%M:%S.%fZ')
|
|
|
|
# entries that are still running don't have a value in the 'end' column
|
|
if not line['end']:
|
|
end = datetime.utcnow()
|
|
else:
|
|
end = datetime.strptime(line['end'], '%Y-%m-%dT%H:%M:%S.%fZ')
|
|
|
|
total += end - start
|
|
|
|
hours = total.total_seconds() / 3600
|
|
# use the settings
|
|
earnings = hours * config['hourly_rate']
|
|
currency = config['currency']
|
|
|
|
print(f'You have earned: ${earnings:.2f} {currency}')
|
|
|
|
Now if you run ``t display -f earnings`` you will get something like:
|
|
|
|
.. code:: text
|
|
|
|
You have earned: 2400 USD
|