# -*- coding: utf-8 -*-
"""
Created on Tue Jun 19 15:28:57 2018

@author: hanye
"""

import datetime

def find_first_day_for_given_start_weekday(year, start_weekday):
    i = 0
    while i<7:
        dayDi = datetime.date(year, 1, 1) + datetime.timedelta(days=i)
        if dayDi.weekday()==start_weekday:
            cal_day1D = dayDi - datetime.timedelta(days=1)
            break
        else:
            cal_day1D = None
        i += 1
    return cal_day1D


def cal_week_no_weekday(dayD, cal_year_day1D):
    if dayD<cal_year_day1D:
        print('dayD must greater or equal to cal_year_day1D!')
        return None
    else:
        cal_week_no = (dayD-cal_year_day1D).days//7 + 1
        cal_weekday = (dayD-cal_year_day1D).days%7 + 1
        return (cal_week_no, cal_weekday)

def find_week_belongs_to(dayT, week_start_iso_weekday=1):
    if isinstance(dayT, datetime.datetime):
        dayD = datetime.date(dayT.year, dayT.month, dayT.day)
    elif isinstance(dayT, datetime.date):
        dayD = dayT
    else:
        print('Wrong type, input parameter must be instance of datetime.datetime '
              'or datetime.date!')
        return None
    calendar_tupe = dayD.isocalendar()
    param_iso_week_no = calendar_tupe[1]
    param_iso_weekday = calendar_tupe[2]
    param_iso_week_year = calendar_tupe[0]
    if isinstance(week_start_iso_weekday, int) and week_start_iso_weekday>0:
        if week_start_iso_weekday==1: # iso week, Mon is weekday 1, Sun is weekday 7
            cal_week_no = param_iso_week_no
            cal_week_year = param_iso_week_year
            cal_weekday = param_iso_weekday
            return (cal_week_year, cal_week_no, cal_weekday)
        else:
            cal_day1D = find_first_day_for_given_start_weekday(dayT.year, week_start_iso_weekday)
            if dayD>=cal_day1D:
                cal_week_year = dayD.year
                cal_week_no, cal_weekday = cal_week_no_weekday(dayD, cal_day1D)
                return (cal_week_year, cal_week_no, cal_weekday)
            else:
                cal_week_year = dayD.year - 1
                cal_day1D = find_first_day_for_given_start_weekday(cal_week_year, week_start_iso_weekday)
                cal_week_no, cal_weekday = cal_week_no_weekday(dayD, cal_day1D)
                return (cal_week_year, cal_week_no, cal_weekday)
    else:
        print('Wrong parameter, must be positive int!')
        return None

def day_by_week_info(week_year, week_no, week_day, week_day_start=1):
    # find first weekday = week_day_start
    day1D = find_first_day_for_given_start_weekday(week_year, week_day_start)
    curr_dayD = day1D + datetime.timedelta(days=(week_no-1)*7+week_day-1)
    return curr_dayD


def test_if_all_week_no_equals_one_on_first_day_in_any_year():
    year = 2000
    collector = []
    while year<=2100:
        print(year)
        dayD = datetime.date(year, 1, 1)
        week_no = dayD.isocalendar()[1]
        if week_no!=1:
            print('Week number of the first day in the year %d is not ONE! It\'s %d'
                  % (year, week_no))
            collector.append(year)
        year += 1
    return collector


# test
if __name__=='__main__':
    i = 1
    dayT = datetime.date(2015, 1, 1)
    dayT1 = datetime.datetime(2015, 1, 1)
    while dayT1<datetime.datetime(2017,1,31):
        r = find_week_belongs_to(dayT1)
        r2 = find_week_belongs_to(dayT1, week_start_iso_weekday=2)
        print('%s, when week starts from 1: %s; when week starts from 2:%s'
              %(dayT1, r, r2))
        dayT1 += datetime.timedelta(days=i)
    print('%s is week_year %d, week_no %d, and week_day %d '
          'when week starts from weekday %d,'
          % (datetime.date(2016, 12, 24), 2016, 47, 3, 2),
          'can be restored by function day_by_week_info(%d, %d, %d, %d): %s'
          % (2016, 47, 3, 2, day_by_week_info(2016, 47, 3, 2)))
