背景
- 這項困難主要發生在[[2022-10-13-mk_emis]]1。
- python datetime.timedelta()函數的特性
- 適用在「精確」時間差的計算,
- 除了年以外的其他時間單位,都還能適用實數的時差
- 所以當面對「概念」性質的跨月時間計算,就不會有
timedelta(months=-1)
這種指令,因為不同月份、潤年與否的前後某幾個月,這種計算是很不明確的,即使只是進行整數月份的計算。 - 實務上以月份為主體的空品模式作業中,跨月計算是作業的常態。以環保署公版模式而言,其生物源、東亞在地區貢獻排放量等2個檔案名稱中,即以前月25日為起始日,而以次月1日的0時為結束,日數還隱含在檔案名稱內,如:
kuang@master /nas2/cmaq2019/download-20220503/input
$ ls -lh */grid03/smoke/b3*
-rw-r--r-- 1 kuang SESAir 173M 4▒▒ 20 14:43 201901/grid03/smoke/b3gts_l.20181225.38.d4.ea2019_d4.tar.xz
-rw-r--r-- 1 kuang SESAir 890M 7▒▒ 19 2021 201902/grid03/smoke/b3gts_l.20190125.35.d4.ea2019_d4.ncf
...
grid03/smoke/b3gts_l.20191025.37.d4.ea2019_d4.tar.xz
-rw-r--r-- 1 kuang SESAir 172M 1▒▒ 11 2022 201912/grid03/smoke/b3gts_l.20191124.38.d4.ea2019_d4.tar.xz
- 檔名中的35、37、38即為各月份檔案的日數,為
當月日數+前月日數-25日+1
的結果。 - 公版模式將日數寫在檔案名稱,好處是
- 直接顯示檔案日數,可以直接控制與檔案大小有關的作業,如搬遷、壓縮、儲存等等。
- 可以直接應用nco指令,在OS層次就完成切割、讀取、整併等等作業,以利測試。(unix的date指令可以接受前、後1個月這樣的計算)
- (其他)
- 然而這樣的作法有其困難處
- 跨年、潤年將會出現問題
- 檔名無規則,需建立複雜、易出錯的對照表
- TEDS進版時,2月份檔名可能會不一樣。
- 解題策略
作法
dateutil.relativedelta的應用
- 將dateutil.relativedelta寫成簡單版本的函數型態,可以回應次月、前月的年份、月份
- dateutil.relativedelta的好處就是與datetime完全融合在日期的計算中,不會像calendar.monthrange()只回應整數。用法幾乎像timedelta一樣,卻又沒有那麼嚴謹。
def rel_mon(dt,im):
a=dt+relativedelta(months=im)
return a.year,a.month
跨月日數的計算
- 次月、前月的年份、月份(
ymn,ymp
)共4個值:以當天為基準,呼叫共同函數rel_mon
、計算相對前後1個的年、月。 - 這4個整數應用在日數的計算。這裡就可以用datetime的相減了。
- 因為未來日定在次月的1日,因此相減後的日數不必再加1
- 日數串成檔案名稱,用以開啟公版模式的排放量檔案。
bdate=datetime.datetime.strptime(tdy,"%Y-%m-%d")
...
mm=tdy.split('-')[1]
smk='/nas2/cmaq2019/download-20220503/input/2019'+mm+'/grid03/smoke/'
ymn,ymp=rel_mon(bdate,+1)[:],rel_mon(bdate,-1)[:] #next and previous month and year[y,m sequence]
days=str((datetime.datetime(ymn[0],ymn[1],1)-datetime.datetime(ymp[0],ymp[1],25)).days)
data_date='2019'+'{:02d}'.format(ymp[1])+'25.'+days
...
fnames=[smk+kind[i]+data_date+'.'+doms[i]+'.ncf' for i in range(nf)]
檢討
- 公版模式將日數寫在檔案名稱,好處是在OS層面的操作,但在胯月程式的設計上,這樣的檔名還造成不小困擾。
- 此處將其名稱規則化、程式化,會更方便未來程式的發展,並減少檔名對照的錯誤。
-
https://sinotec2.github.io/FAQ/2022/10/13/mk_emis.html “ 逐日排放檔案之切割程式” ↩