 函數(shù)計(jì)算年齡與任意兩個(gè)時(shí)間點(diǎn)之間的時(shí)間跨度)
文檔教程知識庫【免費(fèi)下載鏈接】til:memo: Today I Learned項(xiàng)目地址https://gitcode.com/gh_mirrors/ti/til點(diǎn)擊查看免費(fèi)下載在 PostgreSQL 中age()函數(shù)是計(jì)算時(shí)間跨度的利器傳入單個(gè)時(shí)間戳即可得到從該時(shí)刻到現(xiàn)在的年齡如自 Y2K 以來過去了多久傳入兩個(gè)時(shí)間戳則可求出任意兩點(diǎn)之間以年、月、天為單位的時(shí)間差如某個(gè)人的壽命。本文以 postgres/determining-the-age-of-things.md 為主線結(jié)合本倉庫中關(guān)于 interval、timestamp 轉(zhuǎn)換與時(shí)序函數(shù)的多篇 TIL完整講解age()的兩種調(diào)用形式、返回值語義、輸入構(gòu)造方式與實(shí)戰(zhàn)場景。age() 返回的是什么符號化的 intervalage()函數(shù)的返回值類型是 PostgreSQL 的interval。但它的特殊之處在于普通的時(shí)間減法如timestamp1 - timestamp2通常只以天 小數(shù)秒的形式給出結(jié)果而age()會輸出一種**符號化symbolic**的 interval——即把時(shí)間差拆解為X years Y mons Z days這種更接近人類閱讀習(xí)慣的表示這也正是本倉庫 postgres/determining-the-age-of-things.md 示例中輸出16 years 4 mons 12 days的原因。關(guān)于interval數(shù)據(jù)類型的更多定義方式可參考本倉庫 postgres/different-ways-to-define-an-interval.md既可以用interval 3 days關(guān)鍵字加字符串也可以3 days::interval強(qiáng)轉(zhuǎn)還可以通過make_interval(days 3)函數(shù)構(gòu)造。理解interval的表示能力是正確解讀age()返回結(jié)果的前提。單參數(shù)形式age(timestamp) 計(jì)算距今時(shí)長age()最常用的是單參數(shù)形式——傳入一個(gè)時(shí)間戳返回從該時(shí)刻到當(dāng)前時(shí)間的跨度。原文檔中給出的示例是計(jì)算自 Y2K2000 年 1 月 1 日以來已經(jīng)過去了多久 select age(timestamp 2000-01-01); age ------------------------- 16 years 4 mons 12 days這里timestamp 2000-01-01是 PostgreSQL 的標(biāo)準(zhǔn)時(shí)間戳字面量寫法類型關(guān)鍵字 字符串常量。age()會以當(dāng)前日期為基準(zhǔn)做減法輸出結(jié)果是符號化的 interval。在實(shí)際查詢中當(dāng)前時(shí)間也可以顯式指定例如配合本倉庫 postgres/timestamp-functions.md 中介紹的now()等價(jià)于transaction_timestamp()表示當(dāng)前事務(wù)開始時(shí)刻來對比驗(yàn)證-- 結(jié)果隨當(dāng)前時(shí)刻變化例如 select age(now() - interval 3 days); age ------------------ 3 days需要注意age(timestamp)的單參數(shù)形式是按日歷方式計(jì)算整年整月整天的差值而不是按固定的 24 小時(shí)一天來換算這正是它適合表達(dá)年齡這類概念的原因。雙參數(shù)形式age(timestamp1, timestamp2) 計(jì)算兩個(gè)時(shí)間點(diǎn)之差當(dāng)我們需要計(jì)算任意兩個(gè)時(shí)間點(diǎn)之間的跨度時(shí)使用雙參數(shù)形式age(timestamp1, timestamp2)返回timestamp1減去timestamp2的結(jié)果輸出為X years Y mons Z days的形式。原文檔以美國歌手 Prince 為例——傳入死亡日期和出生日期計(jì)算其享年 select age(timestamp April 21, 2016, timestamp June 7, 1958); age -------------------------- 57 years 10 mons 14 days這里兩個(gè)時(shí)間戳都使用了自然語言風(fēng)格的字符串字面量April 21, 2016PostgreSQL 的字符串解析器能夠識別這種表達(dá)并自動轉(zhuǎn)換為 timestamp 類型。輸出57 years 10 mons 14 days即為其實(shí)際壽命。參數(shù)順序與符號含義雙參數(shù)形式的語義是第一個(gè)參數(shù)減去第二個(gè)參數(shù)因此age(2016-04-21, 1958-06-07)得到正值后面的時(shí)間在后若兩個(gè)參數(shù)調(diào)換順序結(jié)果會變成負(fù)數(shù)如-57 years -10 mons -14 days這與 PostgreSQL 中時(shí)間減法保持一致的符號約定參數(shù)既可以是timestamp類型也可以是date類型會按需轉(zhuǎn)換只要保證兩個(gè)參數(shù)的類型可以參與差值運(yùn)算。輸入時(shí)間戳的三種構(gòu)造方式age()的兩個(gè)參數(shù)本質(zhì)上都需要解析為timestamp或可隱式轉(zhuǎn)換的類型。除原文檔展示的字符串字面量寫法如timestamp 2000-01-01外還有以下幾種常見構(gòu)造方式。方式一ISO 8601 字符串直接強(qiáng)轉(zhuǎn)本倉庫 postgres/convert-a-string-to-a-timestamp.md 指出符合 ISO 8601 格式的字符串可以直接::timestamptz強(qiáng)轉(zhuǎn) select 2018-10-24::timestamptz; timestamptz ------------------------ 2018-10-24 00:00:00-05這種形式同樣可以作為age()的參數(shù) select age(2018-10-24::timestamptz);方式二to_timestamp() 按模板解析任意格式當(dāng)字符串不是標(biāo)準(zhǔn) ISO 格式時(shí)可以使用to_timestamp(text, format)按格式模板解析 select to_timestamp(2018-10-24, YYYY-MM-DD); to_timestamp ------------------------ 2018-10-24 00:00:00-05第一個(gè)參數(shù)是待轉(zhuǎn)換的字符串第二個(gè)參數(shù)描述其格式。該方法對非標(biāo)準(zhǔn)輸入如April 21, 2016這類英文日期也能通過Month DD, YYYY模板可靠解析。方式三從列數(shù)據(jù)直接傳入實(shí)際業(yè)務(wù)中最常見的是直接傳入表中存儲的 timestamp/date 列例如計(jì)算用戶年齡、合同剩余天數(shù)select name, age(birth_date) as current_age from users;此時(shí)age(birth_date)直接復(fù)用單參數(shù)形式以當(dāng)前日期為基準(zhǔn)得出每位用戶的年齡配合WHERE條件即可篩選特定年齡段人群。實(shí)戰(zhàn)場景age() 的典型用法場景一計(jì)算記錄距今的時(shí)長結(jié)合本倉庫 postgres/timestamp-functions.md 中介紹的時(shí)間函數(shù)可以靈活地表達(dá)距今多久-- 訂單創(chuàng)建至今的時(shí)間跨度 select order_id, age(created_at) as age_of_order from orders order by created_at desc;場景二過濾指定時(shí)間跨度的記錄利用age()的返回值與interval比較可以過濾出超過 X 時(shí)間的記錄。例如找出注冊超過 1 年的用戶select * from users where age(created_at) interval 1 year;關(guān)于interval字面量的多種寫法詳見 postgres/different-ways-to-define-an-interval.md。場景三以年-月-天形式展示業(yè)務(wù)時(shí)長當(dāng)需要向用戶展示入職 X 年 Y 個(gè)月這類人類可讀的時(shí)長時(shí)age()的符號化輸出正好符合需求免去手動按天數(shù)換算年月的麻煩。注意事項(xiàng)與邊界時(shí)間基準(zhǔn)單參數(shù)age(timestamp)以當(dāng)前日期本地時(shí)區(qū)為基準(zhǔn)結(jié)果會隨時(shí)間推移而變化若需要固定基準(zhǔn)請使用雙參數(shù)形式顯式傳入兩個(gè)時(shí)間戳。返回值不是純天數(shù)age()輸出的是年/月/天符號化結(jié)構(gòu)直接做天數(shù)級別的算術(shù)比較時(shí)建議先將其與interval常量比較或使用EXTRACT(EPOCH FROM interval)轉(zhuǎn)成秒數(shù)。時(shí)區(qū)語義若使用帶時(shí)區(qū)的timestamptz差值計(jì)算基于時(shí)間點(diǎn)本身若使用無時(shí)區(qū)的timestamp則按會話時(shí)區(qū)的日歷語義計(jì)算。構(gòu)造輸入時(shí)建議明確使用帶時(shí)區(qū)類型避免跨時(shí)區(qū)業(yè)務(wù)出現(xiàn)偏差參見 postgres/convert-a-string-to-a-timestamp.md 對timestamptz的說明。日期范圍輔助當(dāng)需要同時(shí)表達(dá)一個(gè)時(shí)間段而非單一跨度時(shí)可參考 postgres/constructing-a-range-of-dates.md 中的daterange()函數(shù)它與age()共同構(gòu)成了 PostgreSQL 處理時(shí)間域的兩類基本工具。小結(jié)age()是 PostgreSQL 中表達(dá)年齡和時(shí)間跨度最直觀的函數(shù)age(timestamp)從當(dāng)前日期算起返回符號化 intervalage(timestamp1, timestamp2)返回兩時(shí)間點(diǎn)之差第一個(gè)減去第二個(gè)同樣以年-月-天呈現(xiàn)輸入支持字符串字面量、ISO 強(qiáng)轉(zhuǎn)、to_timestamp()模板解析以及表列數(shù)據(jù)等多種來源返回結(jié)果可與interval常量比較實(shí)現(xiàn)按時(shí)間跨度過濾等常見需求。完整示例可繼續(xù)閱讀本倉庫的 postgres/determining-the-age-of-things.md該文檔也是本倉庫 READMEREADME.mdPostgres 分類下列出的經(jīng)典 TIL 條目。贊分享文檔教程知識庫【免費(fèi)下載鏈接】til:memo: Today I Learned項(xiàng)目地址https://gitcode.com/gh_mirrors/ti/til點(diǎn)擊查看免費(fèi)下載相關(guān)推薦實(shí)測 Inpaint-web零安裝的瀏覽器圖像修復(fù)與在線圖片超分辨率實(shí)測 Inpaint web零安裝的瀏覽器圖像修復(fù)與在線圖片超分辨率 產(chǎn)品圖上的供應(yīng)商水印你還要再開一次 Photoshopinpaint web 是一款圖像處理AI 應(yīng)用前端StarRocks years_diff 函數(shù)詳解計(jì)算兩個(gè)日期/時(shí)間表達(dá)式之間的年份差StarRocks years_diff 函數(shù)詳解計(jì)算兩個(gè)日期/時(shí)間表達(dá)式之間的年份差 本篇技術(shù)指南圍繞 StarRocks 的 years_diff 日期時(shí)數(shù)據(jù)庫OLAP數(shù)據(jù)倉庫大數(shù)據(jù)湖倉一體數(shù)據(jù)分析Bumbler入門教程3分鐘學(xué)會追蹤Rails項(xiàng)目初始化加載進(jìn)度Bumbler入門教程3分鐘學(xué)會追蹤Rails項(xiàng)目初始化加載進(jìn)度 Bumbler是一款專為Bundler項(xiàng)目設(shè)計(jì)的加載進(jìn)度追蹤工具能幫助開發(fā)者實(shí)時(shí)監(jiān)控Rai開發(fā)工具創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考