[Python] 시간과 날짜, 요일 구하기

2023. 10. 20. 17:18파이썬(Python)

반응형

1. 시간 계산

- 만약 2시 34분에서 5시 43분이 되려면 몇 분이 흘러야 할까?

- 이럴 경우 5시 43분과 2시 34분 사이의 거리와 같다.

- 위 그림에서 0시 0분에서 2시 34분까지의 거리를 A라고 한다.

- 0시 0분에서 5시 43분까지의 거리를 B라고 한다.

- 2시 34분과 5시 43분 사이의 거리는 C이므로 B에서 A를 뺀 값과 같다.

 

- 이를 계산의 편의성으로 시를 분으로 고치면 2시 34분은 2*60+34=154분이 되고 A는 154가 된다.

- 5시 43분은 5*60+43=343분이 되고 A는 343이 된다.

- 따라서 C는 343 - 154 = 189가 되고 189분이 소요되었다는 것을 알 수 있다.

 

a, b, c, d = map(int, input().split())
t1 = a*60+b
t2 = c*60+d
print(f'{a}시 {b}분부터 {c}시 {d}분까지 소요된 시간은 {t2-t1}분입니다.')

 

2 34 5 43
2시 34분부터 5시 43분까지 소요된 시간은 189분입니다.

 

Q) 시간 계산

- a시 b분부터 c시 d분까지 몇 시간 몇 분 소요되었는지 출력하라

- 0 <=a <=c <=23

- 0 <=b <=d <=59

- 조건이 맞지 않으면 재입력을 요구하라.

 

while True:
    a, b, c, d = map(int, input().split())
    if a >= c and b > d:
        print('다시 입력해 주세요.')
        continue
    t1 = a*60+b
    t2 = c*60+d
    minute = t2-t1

    hour = minute // 60
    minute -= 60*hour
    break
print(f'{a}시 {b}분부터 {c}시 {d}분까지 소요된 시간은 {hour}시간 {minute}분입니다.')

 

>> 2 34 2 32
다시 입력해 주세요.
>> 2 34 5 43
2시 34분부터 5시 43분까지 소요된 시간은 3시간 9분입니다.

 

- 입력한 시가 같아도 후에 입력한 분이 더 크면 오류이므로 다시 입력하라는 메시지를 출력한다.

- 입력한 두 시간의 차이를 분 (minute)으로 계산한다.

- 분을 60으로 나누어 시간 (hour)을 계산한다.

- minute을 hour에 60을 곱한 값을 빼서 minute을 갱신한다.

 

 

2. 날짜 계산

- 2월 10일부터 10월 12일까지 며칠이 있을까? (2월은 28일까지 있다고 가정하자.)

- 1월 1일부터 2월 10일까지 일수를 A라 한다.

- 1월 1일부터 10월 12일까지 일수를 B라 한다.

- B에서 A를 뺀 일 수가 2월 11일부터 10월 12일이므로 2월 10일을 포함하기 위해 1을 더한다. (이 값이 C가 된다.)

 

- A는 31+10 = 41이다.

- B는 31+28+31+30+31+30+31+31+30+12 = 285이다.

- C = 285-41+1 = 245이다.

- 따라서 2월 10일부터 10월 12일까지 245일이다.

 

m1, d1, m2, d2 = map(int, input().split())
month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def count_days(m1, d1):
    days = 0
    for m in range(1, m1):
        days += month[m]
    days += d1
    return days


days = count_days(m2, d2)-count_days(m1, d1)+1
print(f'{m1}월 {d1}일부터 {m2}월 {d2}일까지 {days}일 있다.')

 

2 10 10 12
2월 10일부터 10월 12일까지 245일 있다.

 

 

3. 날짜, 시간 혼합 계산

- 만약 5월 8일 11시 10분부터 6월 29일까지 10시 30분까지 얼마나 걸릴까?

m1, d1, h1, n1, m2, d2, h2, n2 = map(int, input().split())


def count_days(m, d):
    days = 0
    month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    for m in range(1, m):
        days += month[m]
    days += d
    return days


def count_time(h, n):
    return h*60+n


days = count_days(m2, d2) - count_days(m1, d1)
time = count_time(h2, n2) - count_time(h1, n1)
if time < 0:
    days -= 1
    time = 24*60+time

hour, minute = time // 60, time % 60
print(f'{m1}월 {d1}일 {h1}시 {n1}분 부터 {m2}월 {d2}일 {h2}시 {n2}분까지 {days}일 {hour}시간 {minute}분 걸립니다.')

 

>> 5 8 11 10 6 29 10 30
5월 8일 11시 10분 부터 6월 29일 10시 30분까지 51일 23시간 20분 걸립니다.

 

- count_days : 날짜를 계산하는 함수이다. 1월 1일부터 m2월 d2일까지의 일 수와 1월 1일부터 m1월 d1일까지의 일 수의 차이를 구한다. (days)

- count_time : 시간을 계산하는 함수이다. 0시 0분부터 h2시 n2분까지의 시간과 0시 0분부터 h1시 n1분까지의 시간의 차이를 구한다. (time)

- 만약 5월 8일 11시 10분부터 6월 29일까지 10시 30분이라면 time의 값이 음수가 나온다. time은 -40이다.

- 또한 days는 52일이 나오는데 이는 5월 8일 11시 10분부터 6월 29일까지 11시 10분을 의미한다.

- 따라서 52일 0시간 0분에서 40분을 빼야 한다.

- 즉, time이 음수이면 24시간인 1440분 (24*60)에서 time을 더한다.

- time의 값은 분이기 때문에 60을 나누어 몫은 시간이 되고 나머지는 분이 된다.

 

 

4. 요일 구하기

- 만약, 2020년 10월 13일이 화요일이라 가정하면, 2023년 10월 13일은 어떤 요일인지 구하라.

- 윤년일 경우 2월은 29일까지이다.

 

y1, m1, d1, weekday = input('날짜와 요일을 입력하라. ').split()
y1, m1, d1 = int(y1), int(m1), int(d1)
y2, m2, d2 = input('요일을 구할 날짜를 입력하라. ').split()
y2, m2, d2 = int(y2), int(m2), int(d2)

week = ['Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat', 'Sun']
month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def leap_year(y):
    if y % 4 == 0:
        if y % 100 == 0:
            if y % 400 == 0:
                return True
            return False
        return True
    return False


def count_days(y, m, d):
    if leap_year(y):
        month[2] = 29
    else:
        month[2] = 28
    return sum(month[:m])+d


a = count_days(y1, m1, d1)

b = 0
for y in range(y1, y2):
    if leap_year(y):
        b += 366
    else:
        b += 365


b += count_days(y2, m2, d2)

c = b-a+week.index(weekday)

print(week[c % 7])

 

>> 날짜와 요일을 입력하라. 2020 10 13 Tue
>> 요일을 구할 날짜를 입력하라. 2035 10 13
Sat

 

- y1, m1, d1을 입력하여 요일을 설정한 후 y2, m2, d2의 요일을 구해야 한다.

- y1년 m1월 d1일부터 y2년 m2월 d2일까지 총며칠이 있는지 계산하여 요일을 구한다.

- A는 y1년 1월 1일부터 y1년 m1월 d1일까지의 일 수이다.

- B는 y1년 1월 1일부터 y2년 m2월 d2일까지의 일 수이다.

- C는 B에서 A를 뺀 값이므로 y1년 m1월 d1일의 다음 날부터  y2년 m2월 d2일까지의 일 수이다.

- 일 수를 구하기 위해 윤년인지 확인한다. 윤년은 4의 배수이면서 100의 배수가 아니어야 한다.

- 또는 100의 배수이지만 400의 배수이면 윤년이다.

- 만약 윤년이면 2월은 29일까지이므로  month 리스트 (월의 일 수)의 2번째 index 값을 29로 바꾼다.

- 윤년이 아니면 2월은 28일이다.

- A를 구하기 위해 month의 리스트에서 0~m1-1 index의 합을 구한 후 d를 더한다. (count_days 함수)

- B를 구하기 위해 y1부터 y2-1까지의 반복문을 통해 윤년인지 확인한다.

- 윤년이면 366일을 더하고 아니면 365일을 더한다. (1년은 365일 또는 366일)

- 남은 일 수인 y2년 1월 1일부터 y2년 m2월 d2일까지 count_days 함수로 계산한다.

- A, B로 인해 C를 구하고 weekday의 index를 추가로 더한다.

- C를 7로 나눈 나머지month의 index가 되고, 그 값은 y2년 m2월 d2일의 요일이 된다.

 

 

Q) 위 문제처럼 요일을 구하는데 이전 날짜의 요일까지 구하여라.

예를 들어, 2023년 10월 19일이 목요일이라면 2021년 10월 19일은 무슨 요일인가?

 

y1, m1, d1, weekday = input('날짜와 요일을 입력하라. ').split()
y1, m1, d1 = int(y1), int(m1), int(d1)
y2, m2, d2 = input('요일을 구할 날짜를 입력하라. ').split()
y2, m2, d2 = int(y2), int(m2), int(d2)

week = ['Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat', 'Sun']
month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def leap_year(y):
    if y % 4 == 0:
        if y % 100 == 0:
            if y % 400 == 0:
                return True
            return False
        return True
    return False


def count_days(y, m, d):
    if leap_year(y):
        month[2] = 29
    else:
        month[2] = 28
    return sum(month[:m])+d


def solve_weekday(y_input, m_input, d_input, y_solve, m_solve, d_solve):
    a = count_days(y_input, m_input, d_input)
    b = 0
    for y in range(y_input, y_solve):
        if leap_year(y):
            b += 366
        else:
            b += 365
    b += count_days(y_solve, m_solve, d_solve)
    return b-a


if (y1, m1, d1) > (y2, m2, d2):
    c = solve_weekday(y2, m2, d2, y1, m1, d1)
    print(week[(c % 7)*(-1)+week.index(weekday)])

else:
    c = solve_weekday(y1, m1, d1, y2, m2, d2)+week.index(weekday)
    print(week[c % 7])

 

>> 날짜와 요일을 입력하라. 2023 10 19 Thr
>> 요일을 구할 날짜를 입력하라. 2003 10 19
Sun

 

- C를 구하는 과정을 함수로 나타내었다. 구하는 과정은 '요일 구하기' 문제를 참고하여라. (solve_weekday)

- 요일이 설정된 날짜 y1, m1, d1과 구해야 할 날짜 y2, m2, d2를 튜플로 묶어 크기 비교를 한다.

- y2, m2, d2의 날짜가 y1, m1, d1보다 더 앞에 왔다면 c에서 7을 나눈 나머지에 -1을 곱하여 weekday의 index만큼 더한다.

- 그 값이 y2, m2, d2의 요일의 index가 된다.

- 예를 들어, c가 16이고 설정된 날짜의 요일이 목요일이다.

- 16일 전의 요일을 구하는 것이므로 2주 전의 이틀 전의 요일을 구한다. 

- 16을 7로 나눈 나머지가 2이고 결국 목요일의 index가 3이면 이틀 전은 index가 1인 화요일이 된다. 

 

 

Q) 요일 개수 구하기

- 2개의 날짜를 입력하고 첫 번째 입력하는 날짜에는 요일을 설정하여 입력한다.

- 개수를 구할 요일을 입력한다.

- 날짜 사이의 요일의 개수를 구하라.

- 예를 들어, 2023년 10월 20일이 금요일이라면 2023년 12월 25일까지 일요일의 개수는 10개이다.

 

y1, m1, d1, weekday = input('날짜와 요일을 입력하라. ').split()
y1, m1, d1 = int(y1), int(m1), int(d1)
y2, m2, d2 = input('날짜를 입력하라. ').split()
y2, m2, d2 = int(y2), int(m2), int(d2)
count_weekday = input('개수를 구할 요일을 입력하라 ')

week = ['Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat', 'Sun']
month = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]


def leap_year(y):
    if y % 4 == 0:
        if y % 100 == 0:
            if y % 400 == 0:
                return True
            return False
        return True
    return False


def count_days(y, m, d):
    if leap_year(y):
        month[2] = 29
    else:
        month[2] = 28
    return sum(month[:m])+d


def solve_weekday(y_input, m_input, d_input, y_solve, m_solve, d_solve):
    a = count_days(y_input, m_input, d_input)
    b = 0
    for y in range(y_input, y_solve):
        if leap_year(y):
            b += 366
        else:
            b += 365
    b += count_days(y_solve, m_solve, d_solve)
    return b-a


def counting_day(weekday, c):
    d = week.index(count_weekday) - week.index(weekday)
    if d < 0:
        c -= 7+d
    else:
        c -= d
    print(c//7+1)


if (y1, m1, d1) > (y2, m2, d2):
    c = solve_weekday(y2, m2, d2, y1, m1, d1)
    weekday2 = week[(c % 7)*(-1)+week.index(weekday)]
    counting_day(weekday2, c)

else:
    c = solve_weekday(y1, m1, d1, y2, m2, d2)
    counting_day(weekday, c)

 

>> 날짜와 요일을 입력하라. 2023 10 20 Fri
>> 날짜를 입력하라. 2023 12 25
>> 개수를 구할 요일을 입력하라 Sun
10

 

- 입력한 두 날짜 사이의 총일수를 먼저 구한다. (solve_weekday 함수로 c를 구한다.)

- 예를 들어 2023년 10월 20일부터 2023년 12월 25일까지 66일이다.

- 2023년 10월 20일을 금요일로 설정했고 개수를 구할 요일이 일요일이라면 금요일에서 2일 후인 10월 22일이 일요일이다.

- 따라서 2023년 10월 22일부터 2023년 12월 25일까지 64일이고, 이는 9주 하고 1일이다. (64를 7로 나눠 몫이 9, 나머지가 1이다.)

- 예를 들어 1주일이면 금요일에서 시작해서 금요일에서 끝나므로 금요일이 2개이다.

- 즉 1주일에 2개가 되므로 n주일에 n+1개가 된다.

- counting_day 함수에서 d는 설정한 요일에서 개수를 구할 요일까지 이동할 수를 구하는 것이다.

- week의 index를 구하고 d를 구해 d만큼 c의 개수를 뺀다.

- 만약 후에 입력한 날짜전에 입력한 날짜보다 빠르면 후에 입력한 날짜의 요일을 먼저 구한다. (weekday2)

- counting_day에서 weekday2를 이용해 d를 구한다.