Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
#!/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)
Считаем рабочие дни с Moment.js