Comments 21
Думаю тут не помешала бы интеграция с одним из плагинов для диапазонов: http://momentjs.com/docs/#/plugins/range/
0
Буду благодарен, если создадите запрос на githubе: github.com/andruhon/moment-weekday-calc/issues
0
Такая же штука на питоне :)
Код
#!/usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/bin/python3.4
# -*- coding: utf-8 -*-
__author__ = 'admin'
api_url = "http://basicdata.ru/api/json/calend/"
from functools import lru_cache
import calendar
import datetime
import urllib.request
import json
def flatten(a):
if isinstance(a, list):
for b in a:
for x in flatten(b):
yield x
else:
yield a
# Генерирует расписание на заданный год по умолчанию
# Все дни с понедельника по пятницу отмечаются рабочими
# Все субботы и воскресенья - выходными
def generate_default_calendar(year):
return group_by_month(
map(lambda x: (x[0], x[1] < 6),
map(lambda x: (x[0], x[1] + 1),
filter(lambda x: x[0] > 0,
flatten(calendar.Calendar.yeardays2calendar(calendar.Calendar(), year))
)
)
)
)
# Разделяет дни на группы по месяцам
def group_by_month_inner(items):
month = []
for day, flag in items:
if month and month[-1][0] > day:
# new month starting
yield month
month = []
month.append((day, flag))
if month:
yield month
def group_by_month(items):
return list(group_by_month_inner(items))
# Загружает дни-исключения
@lru_cache(maxsize=None)
def load_exceptions(apiurl, year):
return json.loads(urllib.request.urlopen(apiurl).read().decode('utf8'))["data"][str(year)]
# Меняет значения структуры по умолчанию для дней-исключений
def apply_exceptions(months, exc):
i = 0
for m in months:
newm = []
i += 1
for d in m:
if str(i) in exc and str(d[0]) in exc[str(i)]:
d = (d[0], exc[str(i)][str(d[0])]["isWorking"] != 2)
newm.append(d)
yield newm
# Удаляет все выходные, конвертирует кортежи в простые дни месяца
def filter_holidays(months):
for m in months:
yield list(
map(
lambda x: x[0],
filter(
lambda x: x[1],
m
)
)
)
# Получает все рабочие дни за определенные месяц/год в виде массива. Если указать месяц, вернет только его
def get_workdays(year=None, month=None):
if year is None and month is None:
year = datetime.datetime.now().year
month = datetime.datetime.now().month
if month is None:
return list(filter_holidays(apply_exceptions(generate_default_calendar(year), load_exceptions(api_url, year))))
else:
return get_workdays(year)[month - 1]
# Считает кол-в рабочих дней в году/месяце
@lru_cache(maxsize=None)
def count_workdays(year=None, month=None):
if month is None and year is None:
return len(get_workdays())
elif month is not None:
return len(get_workdays(year, month))
else:
return sum(list(map(lambda x: len(x), get_workdays(year))), 0)
@lru_cache(maxsize=None)
def _get_expected_hours(year, month, day):
return len(list(filter(lambda x: x < day, get_workdays()))) * 8
# Возвращает сколько часов ты уже должен был отработать
def get_expected_hours():
return _get_expected_hours(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day)
# Считает заработанные деньги исходя из зарплаты и кол-ва отработанны часов
@lru_cache(maxsize=None)
def earned(salary, hours):
return hours / (count_workdays(datetime.datetime.now().year, datetime.datetime.now().month) * 8) * salary
def print_earned_with_stats(hours, salary=None):
if salary is None:
salary = 50000
real = earned(salary, hours)
expected = earned(salary, get_expected_hours())
print("Earned: ", real, " Expected: ", expected)
if real > expected:
print("Well done, you've already earned extra ", real - expected, " money -", hours - get_expected_hours(),
" extra hours worked")
elif real < expected:
print("You should work extra ", get_expected_hours() - hours, " hours to catch schedule")
else:
print("Going on schedule!")
if __name__ == '__main__':
import sys
_salary = None
_hours = None
if len(sys.argv) > 1:
_hours = int(sys.argv[1])
if len(sys.argv) > 2:
_salary = int(sys.argv[2])
if _hours is None:
_hours = 8
print_earned_with_stats(_hours, _salary)
+1
Вот вам сразу реквест — хотите, чтобы ваш плагин использовали — грузите исключения сами :)
Советую basicdata.ru/api/json/calend Описание формата: basicdata.ru/api/calend
Советую basicdata.ru/api/json/calend Описание формата: basicdata.ru/api/calend
0
Спасибо. Стран слишком много в мире — надо будет подумать, как это сделать универсально.
0
Ну тут все просто — конечный результат вам от любого api нужен один — чтобы оно выдавало дни-исключения. Соответственно, можно из любого формата апи приводить к этому, универсальному, и работать с ним. Тогда использующему ваш модуль в очередной стране надо будет только найти апи для нее и реализовать функцию конвертации
0
Быть может заранее заготовить пакеты для стран, которые можно будет установить отдельно? Ну, допустим moment-weekday-calculator-public-holidays-ru и т.д. Как считаете?
0
ну в принципе имеет смысл, вряд ли большинство будет с ним работать более чем в одной стране.
0
Ок. Спасибо. Почешу репу, как время опять будет.
0
Я порекомендовал глянуть в сторону ics.
Парсится слёту, один вопрос — не забыть раз в год утянуть свежий список.
Мне нужен был датский, первый из интернетов —
www.officeholidays.com/ics/ics_country.php?tbl_country=Denmark
На самом деле, это серьёзный вопрос, кому доверять, и не стоит брать вот так вот первый попавшийся.
Парсится слёту, один вопрос — не забыть раз в год утянуть свежий список.
Мне нужен был датский, первый из интернетов —
www.officeholidays.com/ics/ics_country.php?tbl_country=Denmark
На самом деле, это серьёзный вопрос, кому доверять, и не стоит брать вот так вот первый попавшийся.
+1
Кстати еще я не уверен, но вы похоже не учли вариант, что иногда праздничные дни делают рабочими(или если рабочий день в список исключений положить, он станет выходным?)
0
В некоторых странах еще и по отдельным провинциям/землям разные праздники. А есть и плавающие праздники, зависящие от даты пасхи.
0
Будьте осторожны при использовании этого API! Там неправильные данные, например basicdata.ru говорит, что 20 февраля 2015 — сокращенный на 1 час рабочий день, а на самом деле это не так.
0
Ну сокращенные на 1 час я не смотрел, а по кол-ву рабочих/нерабочих дней у них все правильно высчитывалось(сокращенные за рабочий считал)
0
Sign up to leave a comment.
Считаем рабочие дни с Moment.js