LabHub
배우기 러닝패스 코스

銀行現場の言葉

決済日を計算するエンジンをつくる

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

접수 순간과 달력 날짜를 갈라 놓고, 휴장일 달력과 마감시각으로 결제일을 계산하는 엔진을 만든다. 상대 기관의 표준시와 1987·1988년 서울의 서머타임 구간까지 맞게 다루고, 잘못 매겨진 결제일을 원장을 덮어쓰지 않고 전 건 재계산한다.

왜 중요한가

순간은 하나지만 그 순간이 며칠인지는 표준시를 정해야 답이 나온다. 은행에서는 여기에 마감시각과 영업일 달력이 더 붙어서, 돈이 실제로 오가는 날짜는 저장된 사실이 아니라 규칙의 산출물이 된다. 이 계산이 코드 여러 곳에 흩어지면 "어제 거래" 의 정의가 시스템마다 달라지고, 그 어긋남은 장애로 보이지 않아 정산 대사까지 살아남는다. 휴장일과 마감시각은 해마다 바뀌므로 코드가 아니라 데이터에 둔다. 그래서 이 실습의 엔진은 달력과 설정을 --db 로 받은 SQLite 에서 읽는다. 채점기는 여러분이 적어 낸 문구를 믿지 않는다. 자기가 만든 휴장일 달력과 마감시각을 담은 임시 DB 를 물려 여러분의 엔진을 실행하고, 판정을 자기가 계산한 값과 대조한다. 답을 박아 넣은 엔진은 통과하지 못한다.

단계

  1. /root/bizday/gen_bizday.py 를 만들어 실행해 /root/bizday/txn.db 를 만든다. 이체 접수 300건, 이관 거래 48건, 휴장일 6일, 설정 3줄이 들어간다.
  2. UTC 날짜와 KST 날짜가 갈라지는 거래를 /root/bizday/kst_shift.csv 에, 세 숫자를 /root/bizday/bucket.txt 에 적는다.
  3. /root/bizday/bizday.pyis-bizday, next-bizday, add-bizdays 를 구현한다. 달력은 --db 의 holiday 표에서 읽는다.
  4. bizday.pyvalue-date 를 더한다. 마감시각과 표준시는 sys_param 에서 읽는다.
  5. bizday.pylocalize 를 더하고, 서울과 런던에서 날짜가 갈라지는 거래를 /root/bizday/counterparty.csv 에 적는다.
  6. 이관 거래 48건을 /root/bizday/legacy_offsets.csv 에 지역시각과 오프셋까지 적고, 세 숫자를 /root/bizday/dst_seoul.txt 에 적는다.
  7. 원장의 value_date 를 덮어쓰지 말고 txn.dbvalue_date 표를 만들어 300건을 재계산하고, 바뀌는 거래만 /root/bizday/redate.csv 에 적는다.
  8. 재계산한 결제일별 집계를 /root/bizday/valuedate_summary.csv 에, 보고서를 /root/bizday/bizday_report.md 에 쓴다.

참고

접수 원장 스냅샷 만들기

/root/bizday/gen_bizday.py 를 만들어 실행해 /root/bizday/txn.db 를 만드세요. 이체 접수 300건, 이관 거래 48건, 휴장일 6일, 설정 3줄이 들어갑니다.

표 네 개입니다. txn 의 received_utc 는 2026-06-29T01:02:03Z 모양이고, value_date 는 지금 기간계 규칙대로 received_utc 의 앞 10글자를 그대로 씁니다. 그 규칙이 틀렸다는 것이 이 실습의 출발점입니다.

순간과 달력 날짜 갈라 놓기

UTC 날짜와 KST 날짜가 서로 다른 거래를 /root/bizday/kst_shift.csvtxn_id,received_utc,utc_date,kst_date 머리글과 함께 적고, /root/bizday/bucket.txtshift_count=, utc_days=, kst_days= 를 적으세요.

datetime.fromisoformat 으로 순간을 읽고 astimezone(ZoneInfo("Asia/Seoul")) 로 옮긴 뒤 .date() 를 취합니다. 순서를 바꾸면 안 됩니다. utc_days 와 kst_days 는 각각 버킷팅했을 때 나오는 서로 다른 날짜의 수입니다.

영업일 달력을 엔진으로 옮기기

/root/bizday/bizday.pyis-bizday, next-bizday, add-bizdays 를 구현하세요. 휴장일은 --db 로 받은 DB 의 holiday 표에서 읽습니다.

주말은 weekday() >= 5 이고 휴장일은 표에서 옵니다. reason 은 bizday·weekend·holiday 셋 중 하나입니다. 채점기는 학습자 DB 와 다른 휴장일을 담은 임시 DB 를 물려 실행하니, 달력을 코드에 박으면 떨어집니다.

마감시각 뒤의 요청을 익영업일로

bizday.pyvalue-date 를 더하세요. 표준시와 마감시각은 sys_param 에서 읽고, 마감시각 이상이면 하루를 더한 뒤 영업일로 밉니다.

마감시각 비교는 지역시각으로 옮긴 뒤에 합니다. UTC 시각 문자열과 비교하면 서머타임이 있던 구간에서 한 시간씩 어긋납니다. 경계는 >= 입니다 — 정각에 들어온 요청은 넘어갑니다. 채점기는 마감시각을 실행마다 다르게 뽑습니다.

상대 기관의 달력으로 옮기기

bizday.pylocalize 를 더하고, 서울과 런던에서 날짜가 갈라지는 거래를 /root/bizday/counterparty.csvtxn_id,received_utc,seoul_date,london_date 머리글과 함께 적으세요.

utc_offset+09:00 처럼 부호와 두 자리 시·분으로 적습니다. local 은 오프셋이 붙은 RFC 3339 문자열이어야 합니다 — 오프셋을 떼면 그 문자열은 더 이상 순간이 아닙니다. 런던은 여름에 UTC+1 입니다.

1987년 여름의 한 시간 찾아내기

이관 거래 48건을 /root/bizday/legacy_offsets.csvtxn_id,received_utc,seoul_local,utc_offset 로 적고, /root/bizday/dst_seoul.txtkdt_rows=, kst_rows=, date_shift_rows= 를 적으세요.

Asia/Seoul 은 지금 UTC+9 지만 1987·1988년 여름에는 서머타임이 있었습니다. zoneinfo 는 그 사실을 알고 있으니 직접 계산하지 말고 물어보세요. date_shift_rows 는 KST 날짜가 UTC 날짜와 달라지는 이관 거래의 수입니다.

결제일을 원장을 덮어쓰지 않고 다시 계산하기

txn.dbvalue_date(txn_id, value_date) 표를 만들어 300건의 결제일을 재계산해 넣고, 옛 결제일과 달라지는 거래만 /root/bizday/redate.csvtxn_id,received_utc,old_value_date,new_value_date 로 적으세요. txn.value_date 는 건드리지 않습니다.

규칙을 다시 구현하지 말고 bizday.py 를 모듈로 불러 쓰세요 (sys.path 에 /root/bizday 를 넣고 import). 원장이 기록한 옛 결제일을 지우면 어느 규칙으로 매긴 값이었는지 알 수 없게 됩니다. 재계산 결과는 새 표에 담습니다.

집계와 보고서로 옮기기

재계산한 결제일별 건수와 금액을 /root/bizday/valuedate_summary.csvvalue_date,txn_count,amount_sum 로 오름차순으로 적고, /root/bizday/bizday_report.md## 무엇이 틀렸나, ## 결제일을 어떻게 계산하나, ## 상대방 표준시, ## 과거 서머타임, ## 재발 방지 다섯 절을 쓰세요.

집계는 value_date 표와 txn 을 이어 붙이면 나옵니다. 보고서에는 바뀐 건수, 마감시각, 어느 표준시로 계산하는지, 상대 기관의 표준시, 1987·1988년의 오프셋을 숫자와 이름으로 적으세요. 휴장일이 낀 날짜가 집계에서 빠져 있다는 것도 확인할 값어치가 있습니다.