Files
obsidian/obsidian_calendar_generator.py.md
T

379 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import calendar
from datetime import datetime
def generate_universal_calendar():
print("=" * 50)
print(" 옵시디언 캔버스 대형 달력 자동 생성 프로그램 ")
print("=" * 50)
# 1. 사용자로부터 연도 및 월 입력 받기
try:
year = int(input("▶ 생성할 연도를 입력하세요 (예: 2026): "))
month = int(input("▶ 생성할 월을 입력하세요 (1~12): "))
if not (1 <= month <= 12):
print("❌ 월은 1부터 12 사이의 숫자여야 합니다.")
return
except ValueError:
print("❌ 올바른 숫자를 입력해주세요.")
return
# 2. 달력의 레이아웃 및 크기 기본 사양 정의
card_width = 320
day_height = 140
box_height = 100
gap_x = 20
gap_y = 20
# 일자 카드 1개 + 하단 10개 박스가 차지하는 1주일 행(Row)의 총 높이
row_total_height = day_height + gap_y + (box_height * 10) + (gap_y * 10) # 1380px
# 3. 해당 월의 요일 정보 및 일수 자동 계산
# weekday_start: 0(월요일) ~ 6(일요일)
# num_days: 해당 월의 총 일수 (28~31)
weekday_start, num_days = calendar.monthrange(year, month)
# 일요일 시작 달력 규격을 위해 인덱스 조정 (기본 파이썬은 월요일 시작)
# 파이썬(월=0, 화=1 ... 토=5, 일=6) -> 변경(일=0, 월=1, 화=2 ... 토=6)
start_offset = (weekday_start + 1) % 7
nodes = []
# 4. 최상단 대형 메인 헤더 타이틀 생성
nodes.append({
"id": "calendar-main-title",
"type": "text",
"text": f"# 📅 {year}년 {month}월 (Calendar)",
"x": 0,
"y": -120,
"width": (card_width * 7) + (gap_x * 6), # 7열 전체 폭에 정렬 (2360px)
"height": 100,
"color": "3" # 노란색 강조
})
# 5. 고정 요일 머리글 배치 (일요일 ~ 토요일 순서)
weekdays = [
{"name": "☀️ 일요일", "color": "1"}, # 일요일 주황/적색 강조
{"name": "월요일", "color": None},
{"name": "화요일", "color": None},
{"name": "수요일", "color": None},
{"name": "목요일", "color": None},
{"name": "금요일", "color": None},
{"name": "🐳 토요일", "color": "2"} # 토요일 청색 강조
]
for idx, day_info in enumerate(weekdays):
w_node = {
"id": f"w-header-{idx}",
"type": "text",
"text": f"### {day_info['name']}",
"x": idx * (card_width + gap_x),
"y": 0,
"width": card_width,
"height": 60
}
if day_info["color"]:
w_node["color"] = day_info["color"]
nodes.append(w_node)
# 6. 일자 배치 및 일자별 하단 10개 텍스트 상자 자동 배치 루프
for day in range(1, num_days + 1):
# 시작 요일(offset)을 반영하여 현재 일자가 위치할 7열 바둑판 좌표 계산
grid_pos = (start_offset + day - 1) % 7
week_row = (start_offset + day - 1) // 7
# 현재 일자의 시작 X, Y 물리 좌표 산출
current_x = grid_pos * (card_width + gap_x)
current_y = 80 + (week_row * row_total_height)
# 주말 컬러 색상 코드 할당
day_color = None
if grid_pos == 0: # 일요일
day_color = "1"
elif grid_pos == 6: # 토요일
day_color = "2"
# 메인 일자 노드 삽입
day_node = {
"id": f"day-node-{day}",
"type": "text",
"text": f"## {day}",
"x": current_x,
"y": current_y,
"width": card_width,
"height": day_height
}
if day_color:
day_node["color"] = day_color
nodes.append(day_node)
# 일자 노드 바로 아래에 10단 텍스트 레이어 수직 배치
box_start_y = current_y + day_height + gap_y
for b_idx in range(1, 11):
box_node = {
"id": f"day-{day}-slot-{b_idx}",
"type": "text",
"text": "",
"x": current_x,
"y": box_start_y + ((b_idx - 1) * (box_height + gap_y)),
"width": card_width,
"height": box_height
}
nodes.append(box_node)
# 7. 옵시디언 캔버스 데이터 최종 통합 규칙 선언
canvas_json_structure = {
"nodes": nodes,
"edges": []
}
# 8. 파일로 내보내기 수행
output_filename = f"{year}년_{month}월_대형달력.canvas"
with open(output_filename, "w", encoding="utf-8") as file:
json.dump(canvas_json_structure, file, ensure_ascii=False, indent=2)
print("-" * 50)
print(f"🎉 작성이 완료되었습니다! 총 {len(nodes)}개의 개체가 구성되었습니다.")
print(f"💾 생성된 파일명: {output_filename}")
print("💡 팁: 해당 파일을 옵시디언 보관소(Vault)에 넣어 즉시 열어보세요.")
print("=" * 50)
if __name__ == "__main__":
generate_universal_calendar()
---
이 파이썬 코드를 초보자도 이해할 수 있게 설명해드릴게요!
---
## 🐍 전체 목적
**Obsidian 캔버스용 월간 달력 파일을 자동으로 만들어주는 프로그램이에요.**
사용자가 연도(2026)와 월(10)을 입력하면, Obsidian에서 바로 열 수 있는 `.canvas` 파일을 생성해요.
---
## 📦 사용하는 도구 (import)
```python
import json # JSON 파일 읽기/쓰기
import calendar # 달력 계산 (해당 월의 시작 요일, 총 일수)
from datetime import datetime # 날짜 관련 (현재는 직접 사용 안 함)
```
---
## 🔢 전체 흐름
```
1. 연도, 월 입력 받기
2. 카드 크기/간격 설정
3. 달력 계산 (시작 요일, 총 일수)
4. 메인 제목 카드 생성
5. 요일 헤더 카드 7개 생성 (일~토)
6. 날짜별 카드 생성 (날짜 카드 1개 + 빈 슬롯 10개)
7. JSON으로 묶기
8. .canvas 파일로 저장
```
---
## 📐 레이아웃 설정
```python
card_width = 320 # 카드 가로 크기 (픽셀)
day_height = 140 # 날짜 카드 세로 크기
box_height = 100 # 빈 슬롯 카드 세로 크기
gap_x = 20 # 카드 사이 가로 간격
gap_y = 20 # 카드 사이 세로 간격
```
캔버스는 좌표계(x, y)로 카드를 배치해요. 픽셀 단위로 위치를 직접 계산해야 해요.
---
## 🗓️ 달력 계산의 핵심
```python
weekday_start, num_days = calendar.monthrange(year, month)
```
예) `calendar.monthrange(2026, 10)` → `(3, 31)`
- `3` = 10월 1일이 목요일 (0=월, 1=화, 2=수, **3=목**, 4=금, 5=토, 6=일)
- `31` = 10월은 31일까지
```python
start_offset = (weekday_start + 1) % 7
```
파이썬은 월요일=0으로 시작하는데, 이 달력은 **일요일=0**으로 시작해요.
그래서 +1 후 %7로 인덱스를 조정해요.
---
## 📍 날짜 위치 계산
각 날짜가 캔버스 어디에 놓일지 계산하는 핵심 공식이에요:
```python
grid_pos = (start_offset + day - 1) % 7 # 0~6열 (일~토)
week_row = (start_offset + day - 1) // 7 # 몇 번째 주(행)인지
current_x = grid_pos * (card_width + gap_x) # 가로 위치
current_y = 80 + (week_row * row_total_height) # 세로 위치
```
예) 2026년 10월 1일 (목요일)
- `start_offset` = 4 (목요일이 일 기준 4번째 열)
- `grid_pos` = (4 + 1 - 1) % 7 = **4** → 5번째 열
- `week_row` = (4 + 1 - 1) // 7 = **0** → 첫 번째 행
---
## 🃏 카드(노드) 구조
Obsidian 캔버스의 카드는 이런 JSON 구조예요:
```json
{
"id": "day-node-1", // 고유 ID (겹치면 안 됨)
"type": "text", // 텍스트 카드
"text": "## 1", // 카드 안에 표시될 내용 (마크다운)
"x": 1400, // 가로 위치
"y": 80, // 세로 위치
"width": 320, // 카드 너비
"height": 140, // 카드 높이
"color": "1" // 색상 (선택사항, 1=빨강, 2=파랑, 3=노랑...)
}
```
---
## 🗂️ 날짜 1개당 생성되는 카드 수
날짜 하나당 총 **11개**의 카드가 생겨요:
```
┌─────────────┐ ← 날짜 카드 (예: "## 1")
├─────────────┤ ← 빈 슬롯 1
├─────────────┤ ← 빈 슬롯 2
│ ... │
└─────────────┘ ← 빈 슬롯 10
```
31일 기준 → 31 × 11 = **341개** + 제목/요일 헤더 = 총 **350개** 카드
---
## 💾 파일 저장
```python
canvas_json_structure = {
"nodes": nodes, # 모든 카드 목록
"edges": [] # 연결선 (이 달력엔 없음)
}
with open(output_filename, "w", encoding="utf-8") as file:
json.dump(canvas_json_structure, file, ensure_ascii=False, indent=2)
```
`.canvas` 파일은 사실 **JSON 파일**이에요. Obsidian이 이 JSON을 읽어서 시각적인 캔버스로 보여주는 거예요.
---
## 🚀 실행 방법
```bash
python 파일명.py
```
실행하면:
```
▶ 생성할 연도를 입력하세요 (예: 2026): 2026
▶ 생성할 월을 입력하세요 (1~12): 10
→ 2026년_10월_대형달력.canvas 파일 생성!
```
이 파일을 Obsidian Vault 폴더에 넣으면 바로 열 수 있어요 😊
---
## `%` 와 `//` 설명
---
### `%` — 나머지 연산자
나눗셈 후 **나머지**만 반환해요.
```python
10 % 3 = 1 # 10 ÷ 3 = 3 나머지 1
7 % 7 = 0 # 7 ÷ 7 = 1 나머지 0
5 % 7 = 5 # 5 ÷ 7 = 0 나머지 5
```
달력 코드에서는 이렇게 써요:
```python
grid_pos = (start_offset + day - 1) % 7
```
`% 7` 을 하면 결과가 항상 **0~6 사이**로 유지돼요.
→ 7이 되면 다시 0으로 돌아가서 **열(日~土)을 반복**하는 데 쓰여요.
```
0→일 1→월 2→화 3→수 4→목 5→금 6→토
7→다시 0(일) 8→1(월) ...
```
---
### `//` — 몫 연산자 (버림 나눗셈)
나눗셈 후 **소수점을 버리고 정수만** 반환해요.
```python
10 // 3 = 3 # 10 ÷ 3 = 3.33... → 3
7 // 7 = 1 # 7 ÷ 7 = 1.0 → 1
5 // 7 = 0 # 5 ÷ 7 = 0.71... → 0
```
달력 코드에서는 이렇게 써요:
```python
week_row = (start_offset + day - 1) // 7
```
`// 7` 을 하면 **몇 번째 주(행)인지** 알 수 있어요.
```
1~7번째 날 → 0 (첫 번째 주)
8~14번째 날 → 1 (두 번째 주)
15~21번째 날 → 2 (세 번째 주)
...
```
---
### 두 개를 함께 보면
```python
grid_pos = (start_offset + day - 1) % 7 # 몇 번째 열? (가로 위치)
week_row = (start_offset + day - 1) // 7 # 몇 번째 행? (세로 위치)
```
예) 10월 10일, `start_offset = 4` 라면:
```
(4 + 10 - 1) = 13
13 % 7 = 6 → 6번째 열 = 토요일
13 // 7 = 1 → 1번째 행 = 2번째 주
```
이 두 연산자로 날짜를 **바둑판 좌표**에 배치하는 거예요! 😊