實務上常需要對 API 所回傳的 Date 字串加工,如先增加 hours
,再增加 title
,這牽涉到增加 Date 與 String 兩種 Type,該如何優雅實現呢 ?
Version
macOS Catelina 10.15.1
VS Code 1.40.0
Quokka 1.0.259
Ramda 0.26.1
Date-fp 5.0.3
Imperative
let data = '2019-06-13 07:43:44'
let fn = str => {
let date = new Date(str)
date.setHours(date.getHours() + 8)
return 'Release : ' + date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate() + ' ' +
date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds()
};
fn(data) // ?
Imperative 會直接使用 Date 自帶的 getHours()
取得 hour 部分,+8
之後再使用 setHours()
寫回,其中 setHours()
使用了 side effect 改變 date
。
最後加上 發生日期
,並還原日期原本格式。
Function Pipeline
import { pipe, concat } from 'ramda'
import { add, format, parse } from 'date-fp'
let data = '2019-06-13 07:43:44'
let fn = pipe(
parse('YYYY-MM-DD HH:mm:ss'),
add('hours', 8),
format('YYYY-MM-DD HH:mm:ss'),
concat('Release : ')
)
fn(data) // ?
以 functional 角度思考:
- 使用 date-fp 的
parse()
將 string 轉成 date - 使用 date-fp 的
add()
增加8
小時 - 使用 date-fp 的
format()
還原日期原本格式 - 使用 Ramda 的
concat()
加上發生時間
最後以 pipe()
整合所有流程,非常清楚。
Function Composition
import { compose, concat } from 'ramda'
import { add, format, parse } from 'date-fp'
let data = '2019-06-13 07:43:44'
let fn = compose(
concat('Release : '),
format('YYYY-MM-DD HH:mm:ss'),
add('hours', 8),
parse('YYYY-MM-DD HH:mm:ss')
)
fn(data) // ?
既然能使用 pipe()
達成 pipeline,反向使用 compose()
就是 function composition 了。
Conclusion
- Ramda 缺乏處理 Date 的 function,可靠 Date-fp 補齊
- 相同的功能, imperative 與 functional 何者較優雅呢 ?
Reference
date-fp, add()
date-fp, format()
Ramda, pipe()
Ramda, compose()
Ramda, concat()