Skip to content

Commit

Permalink
Add option to specify start of the week (#240)
Browse files Browse the repository at this point in the history
* Add function that offsets week start

* Apply offset when week option is used

* Add tests

* Update configuration docs

* Add default fallback value
  • Loading branch information
pedrorivotti authored and k4nar committed Jan 4, 2019
1 parent 01026f9 commit 5cdf1c4
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 5 deletions.
8 changes: 8 additions & 0 deletions docs/user-guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,13 @@ Globally configure how `dates` should be formatted. All [python's `strftime` dir

Globally configure how `time` should be formatted. All [python's `strftime` directives](http://strftime.org) are supported.

#### `options.week_start`

Globally configure which day corresponds to the start of a week. Allowable
values are `monday` (default), `tuesday`, `wednesday`, `thursday`, `friday`,
`saturday`, and `sunday`.


### Default tags

Tags can be automatically added for selected projects. This is convenient when
Expand Down Expand Up @@ -211,6 +218,7 @@ stop_on_start = true
stop_on_restart = false
date_format = %Y.%m.%d
time_format = %H:%M:%S%z
week_start = monday
log_current = false
pager = true
report_current = false
Expand Down
22 changes: 20 additions & 2 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
"""Unit tests for the 'utils' module."""

import arrow
import functools
import os
import datetime
Expand All @@ -13,8 +14,8 @@
import pytest
from dateutil.tz import tzutc

from watson.utils import (get_start_time_for_period, make_json_writer,
safe_save, parse_tags, PY2)
from watson.utils import (apply_weekday_offset, get_start_time_for_period,
make_json_writer, safe_save, parse_tags, PY2)
from . import mock_datetime


Expand All @@ -41,6 +42,23 @@ def test_get_start_time_for_period(now, mode, start_time):
assert get_start_time_for_period(mode).datetime == start_time


@pytest.mark.parametrize("monday_start, week_start, new_start", [
("2018 12 3", "monday", "2018 12 3"),
("2018 12 3", "tuesday", "2018 12 4"),
("2018 12 3", "wednesday", "2018 12 5"),
("2018 12 3", "thursday", "2018 12 6"),
("2018 12 3", "friday", "2018 11 30"),
("2018 12 3", "saturday", "2018 12 1"),
("2018 12 3", "sunday", "2018 12 2"),
("2018 12 3", "typo", "2018 12 3"),
])
def test_apply_weekday_offset(monday_start, week_start, new_start):
with mock_datetime(_dt(2018, 12, 6), datetime):
original_start = arrow.get(monday_start, "YYYY MM D")
result = arrow.get(new_start, "YYYY MM D")
assert apply_weekday_offset(original_start, week_start) == result


def test_make_json_writer():
fp = StringIO()
writer = make_json_writer(lambda: {'foo': 42})
Expand Down
14 changes: 11 additions & 3 deletions watson/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

from . import watson as _watson
from .frames import Frame
from .utils import (format_timedelta, get_frame_from_argument,
get_start_time_for_period, options, safe_save,
sorted_groupby, style, parse_tags)
from .utils import (apply_weekday_offset, format_timedelta,
get_frame_from_argument, get_start_time_for_period,
options, safe_save, sorted_groupby, style, parse_tags)


class MutuallyExclusiveOption(click.Option):
Expand Down Expand Up @@ -57,6 +57,14 @@ def convert(self, value, param, ctx):
# expected by the user, so that midnight is midnight in the local
# timezone, not in UTC. Cf issue #16.
date.tzinfo = tz.tzlocal()

# Add an offset to match the week beginning specified in the
# configuration
if param.name == "week":
week_start = ctx.obj.config.get(
"options", "week_start", "monday")
date = apply_weekday_offset(
start_time=date, week_start=week_start)
return date


Expand Down
17 changes: 17 additions & 0 deletions watson/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,23 @@ def get_start_time_for_period(period):
return start_time


def apply_weekday_offset(start_time, week_start):
"""
Apply the offset required to move the start date `start_time` of a week
starting on Monday to that of a week starting on `week_start`.
"""
weekdays = dict(zip(
["monday", "tuesday", "wednesday", "thursday", "friday", "saturday",
"sunday"], range(0, 7)))

new_start = week_start.lower()
if new_start not in weekdays:
return start_time
now = datetime.datetime.now()
offset = weekdays[new_start] - 7 * (weekdays[new_start] > now.weekday())
return start_time.replace(days=offset)


def make_json_writer(func, *args, **kwargs):
"""
Return a function that receives a file-like object and writes the return
Expand Down

0 comments on commit 5cdf1c4

Please sign in to comment.