|
|
목표를 정하고 그것을 이루기 위해 얼마나 시간이 남았는지 혹은 목표를 세우고 지금 얼마나 지났는지를 컴퓨터 화면 한쪽에 표시하고 늘 목표지향적인 삶을 살고 싶어 작은 Dday 프로그램을 만들어 봤다.
1. 미래 혹은 과거 특정 일자로부터 오늘까지 며칠이 차이가 나는지 계산하는 가장 간단한 프로그램을 코딩하려면 먼저 파이썬(Python) 프로그램을 컴퓨터에 다운 받아야 한다. 그리고 이 프로그램을 컴퓨터 화면에 위젯이나 항상 위에 떠 있는 창처럼 계속 띄워두고 싶다면, 파이썬의 기본 그래픽 라이브러리인 tkinter를 사용해 작은 프로그램 창을 만들면 된다.
1) 파이썬 공식 홈페이지(python.org)에 접속한다.
2) Downloads 메뉴에서 노란색 [Download Python 3.xx.x] 버튼을 클릭해 설치 파일을 받는다.
3) 다운로드한 설치 파일을 실행한다.
4) [중요] 설치 창 맨 아래에 있는 Add python.exe to PATH 체크박스에 적극적으로 반드시 체크를 해야 한다. 이때 첫 번째 (관리자 권한 또는 경로 설정 관련)와 두 번째 Add Python to PATH 모두 체크한다.
5) [Install Now]를 눌러 설치를 완료한다
2. 프로그램 짜기
1) 윈도우 빈 화면에 오른쪽 마우스를 클릭하고 메모장을 새로 연다.
2) 아래 내용을 그대로 복사해서 메모장에 집어 넣는다. 참고로 오늘 날짜가 2026년 9월 15일이므로, 과거 날짜를 예시로 2026년 1월 1일로 세팅해 두었는데 기준일을 원하는 날짜로 바꾸어도 다
from datetime import date
import tkinter as tk
import os
# 날짜를 저장할 파일 이름
CONFIG_FILE = "dday_config.txt"
def load_date():
"""저장된 날짜를 불러오는 함수"""
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, "r") as f:
parts = f.read().strip().split(",")
return int(parts[0]), int(parts[1]), int(parts[2])
except:
pass
return 2026, 1, 1 # 기본값
def save_date(y, m, d):
"""입력한 날짜를 파일에 저장하는 함수"""
with open(CONFIG_FILE, "w") as f:
f.write(f"{y},{m},{d}")
def calculate_and_update():
"""입력받은 날짜로 디데이를 계산하고 화면을 갱신하는 함수"""
try:
y = int(entry_year.get())
m = int(entry_month.get())
d = int(entry_day.get())
# 실제 존재하는 날짜인지 검증 및 계산
past_date = date(y, m, d)
today = date.today()
delta = today - past_date
# 화면 갱신
label_title.config(text=f"{y}/{m}/{d} 로부터")
label_days.config(text=f"{delta.days} 일째")
label_error.config(text="") # 에러 메시지 삭제
# 날짜 저장
save_date(y, m, d)
except ValueError:
label_error.config(text="올바른 날짜를 입력하세요.", fg="#e74c3c")
# 저장된 이전 날짜 가져오기
init_y, init_m, init_d = load_date()
days_init = (date.today() - date(init_y, init_m, init_d)).days
# GUI 창 설정
root = tk.Tk()
root.title("디데이 카운터")
root.geometry("260x170+1000+600") # 입력창 공간을 위해 높이를 조금 늘렸습니다.
root.configure(bg="#2c3e50")
root.attributes("-topmost", True)
# --- 상단: 디데이 표시부 ---
label_title = tk.Label(root, text=f"{init_y}/{init_m}/{init_d} 로부터", font=("맑은 고딕", 10), fg="#ecf0f1", bg="#2c3e50")
label_title.pack(pady=(10, 0))
label_days = tk.Label(root, text=f"{days_init} 일째", font=("맑은 고딕", 20, "bold"), fg="#e74c3c", bg="#2c3e50")
label_days.pack(pady=2)
# --- 하단: 날짜 입력부 ---
frame_input = tk.Frame(root, bg="#2c3e50")
frame_input.pack(pady=5)
entry_year = tk.Entry(frame_input, width=5, justify="center")
entry_year.insert(0, str(init_y))
entry_year.pack(side="left", padx=2)
tk.Label(frame_input, text="년", fg="white", bg="#2c3e50").pack(side="left")
entry_month = tk.Entry(frame_input, width=3, justify="center")
entry_month.insert(0, str(init_m))
entry_month.pack(side="left", padx=2)
tk.Label(frame_input, text="월", fg="white", bg="#2c3e50").pack(side="left")
entry_day = tk.Entry(frame_input, width=3, justify="center")
entry_day.insert(0, str(init_d))
entry_day.pack(side="left", padx=2)
tk.Label(frame_input, text="일", fg="white", bg="#2c3e50").pack(side="left")
# 변경 버튼
btn_update = tk.Button(frame_input, text="변경", command=calculate_and_update, bg="#34495e", fg="white", bd=0, padx=5)
btn_update.pack(side="left", padx=5)
# 에러 메시지 표시용 레이블
label_error = tk.Label(root, text="", font=("맑은 고딕", 9), bg="#2c3e50")
label_error.pack()
root.mainloop()
3) 메모장 왼쪽 위 메뉴에서 [파일], [다른 이름으로 저장]을 누른다. 참고로 [가장 중요] 저장 창이 뜨면 아래 두 가지를 반드시 확인해야 한다. 파일 형식: 클릭해서 텍스트 문서(*.txt)를 모든 파일 (*.*)로 변경한다. 파일 이름: 원래 적혀있던 내용을 다 지우고 dday.pyw 라고 정확하게 입력한다. 그리고 저장위치를 정하고 [저장] 버튼을 누른다.
3. 본인의 경우는 바탕화면에 저장했다. 바탕화면에 새로 만들어진 dday.pyw 파일을 더블 클릭해 보고만약 이렇게 했는데도 아무 반응이 없다면, 방금 만든 dday.pyw 파일에 마우스 우클릭 [연결 프로그램] 에서 다운받은 [Python] 혹은 [Python Launcher for Windows]를 다시 한번 선택해 주시면 정상적으로 화면에 작은 카운터 창이 나타난다. 창 아래쪽에 [ 년 ] [ 월 ] [ 일 ]을 입력할 수 있는 빈칸과 [변경] 버튼이 보이는데 원하는 숫자를 타이핑하고 [변경]을 누르면, 메모장을 열 필요 없이 화면에서 바로 계산되어 숫자가 바뀐다!
그리고 이 프로그램이 컴퓨터를 킬 때마다 자동으로 시작되려면
1. 키보드의 윈도우 키(Window) + R 키를 동시에 누른다. (화면 왼쪽 아래에 '실행' 창이 뜹니다.)
2. 입력창에 아래 명령어를 그대로 적고 엔터(Enter)를 누른다.
shell:startup
3. 그러면 화면에 [시작프로그램]이라는 이름의 빈 폴더 창이 열린다.
4. 이 때 dday.pyw 파일을 복사해 시작프로그램 폴더 안에 넣는다. 그러면 컴퓨터를 켜고 윈도우 바탕화면이 나올 때, 아무것도 누르지 않아도 몇 초 뒤 화면 구석에 디데이 카운터 창이 자동으로 알아서 나타나게 다.
5. 만일 기존에 만들어진 Dday 창이 약간 커보인다면 dday.pyw 파일을 메모장으로 열고, 46번째 줄 근처에 있는 root.geometry 코드를 찾아서 아래와 같이 숫자를 줄여주면 된다.
root.geometry("260x170+1000+600") => root.geometry("200x120+1000+600")
6. 숫자 의미 (참고용)
200: 창의 가로 크기 (더 좁게 만들려면 숫자를 낮춘다)
120: 창의 세로 크기 (더 슬림하게 만들려면 숫자를 낮춘다)
뒤쪽의 +1000+600은 화면에 처음 뜰 때의 모니터 위치를 말한다. 숫자를 수정한 뒤 저장(Ctrl + S)하고 프로그램을 다시 켜시면 눈에 띄게 미니멀해진 창을 확인하실 수 있다!
흠... 다 만들고 보니 날짜가 자동으로 계산되서 날이 바뀌어도 나와야 하는데 지금 이것은 기준일을 넣어주면 그것만 표시하게 되어 있다. 따라서 1분단위로 날짜를 체크 다음날로 바뀌면 D +, - 몇일인지 계산하여 표시하도록 다음과 같이 수정하였다. 여러분도 필요하시면 아래 내용을 카피하여 메모장에 넣고 update 하시기 바란다.
from datetime import date
import tkinter as tk
import os
# 날짜를 저장할 파일 이름
CONFIG_FILE = "dday_config.txt"
current_today = date.today() # 현재 프로그램이 인식하고 있는 '오늘' 날짜 저장
def load_date():
"""저장된 날짜를 불러오는 함수"""
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, "r") as f:
parts = f.read().strip().split(",")
if len(parts) == 3:
return int(parts[0]), int(parts[1]), int(parts[2])
except Exception:
pass
return 2026, 1, 1 # 기본값
def save_date(y, m, d):
"""입력한 날짜를 파일에 저장하는 함수"""
try:
with open(CONFIG_FILE, "w") as f:
f.write(f"{y},{m},{d}")
except Exception:
pass
def get_dday_string(target_date):
"""과거일 경우 '~일째', 미래일 경우 'D-~' 문자열을 반환하는 함수"""
today = date.today()
delta = target_date - today
if delta.days > 0:
return f"D-{delta.days}"
elif delta.days == 0:
return "D-Day"
else:
return f"{-delta.days + 1} 일째"
def update_display():
"""화면의 디데이 표시를 새로고침하는 함수"""
try:
y = int(entry_year.get())
m = int(entry_month.get())
d = int(entry_day.get())
target_date = date(y, m, d)
dday_text = get_dday_string(target_date)
label_title.config(text=f"{y}/{m}/{d} 기준으로")
label_days.config(text=dday_text, fg="#e74c3c" if "D-" in dday_text else "#2ecc71")
label_error.config(text="")
return True
except ValueError:
label_error.config(text="올바른 날짜를 입력하세요.", fg="#e74c3c")
return False
def calculate_and_update():
"""[변경] 버튼을 눌렀을 때 실행되는 함수"""
if update_display():
y = int(entry_year.get())
m = int(entry_month.get())
d = int(entry_day.get())
save_date(y, m, d)
def check_midnight_and_loop():
"""매 분마다 날짜가 바뀌었는지 체크하고 자동 갱신하는 루프 함수"""
global current_today
today = date.today()
# 실제 날짜가 변경되었을 때만 화면을 갱신합니다.
if today != current_today:
current_today = today
update_display()
# 60000밀리초(1분) 후에 이 함수를 다시 실행합니다.
root.after(60000, check_midnight_and_loop)
# 저장된 이전 날짜 가져오기
init_y, init_m, init_d = load_date()
# GUI 창 설정
root = tk.Tk()
root.title("디데이 카운터")
root.geometry("260x170+1000+600")
root.configure(bg="#2c3e50")
root.attributes("-topmost", True)
# --- 상단: 디데이 표시부 ---
label_title = tk.Label(root, text=f"{init_y}/{init_m}/{init_d} 기준으로", font=("맑은 고딕", 10), fg="#ecf0f1", bg="#2c3e50")
label_title.pack(pady=(10, 0))
label_days = tk.Label(root, text="", font=("맑은 고딕", 20, "bold"), bg="#2c3e50")
label_days.pack(pady=2)
# --- 하단: 날짜 입력부 ---
frame_input = tk.Frame(root, bg="#2c3e50")
frame_input.pack(pady=5)
entry_year = tk.Entry(frame_input, width=5, justify="center")
entry_year.insert(0, str(init_y))
entry_year.pack(side="left", padx=2)
tk.Label(frame_input, text="년", fg="white", bg="#2c3e50").pack(side="left")
entry_month = tk.Entry(frame_input, width=3, justify="center")
entry_month.insert(0, str(init_m))
entry_month.pack(side="left", padx=2)
tk.Label(frame_input, text="월", fg="white", bg="#2c3e50").pack(side="left")
entry_day = tk.Entry(frame_input, width=3, justify="center")
entry_day.insert(0, str(init_d))
entry_day.pack(side="left", padx=2)
tk.Label(frame_input, text="일", fg="white", bg="#2c3e50").pack(side="left")
# 변경 버튼
btn_update = tk.Button(frame_input, text="변경", command=calculate_and_update, bg="#34495e", fg="white", bd=0, padx=5)
btn_update.pack(side="left", padx=5)
# 에러 메시지 표시용 레이블
label_error = tk.Label(root, text="", font=("맑은 고딕", 9), bg="#2c3e50")
label_error.pack()
# 초기 화면 표시 및 자동 갱신 루프 시작
update_display()
check_midnight_and_loop()
root.mainloop()
