age
được tính bằng timestamptz_age
hàm trong src/backend/utils/adt/timestamp.c
. Nhận xét cho biết:
/* timestamptz_age()
* Calculate time difference while retaining year/month fields.
* Note that this does not result in an accurate absolute time span
* since year and month are out of context once the arithmetic
* is done.
*/
Đầu tiên, mã chuyển đổi các đối số thành struct pg_tm
biến tm1
và tm2
(struct pg_tm
tương tự như struct tm
của thư viện C , nhưng có các trường múi giờ bổ sung) và sau đó tính toán sự khác biệt tm
mỗi trường.
Trong trường hợp của age('2018-07-01','2018-05-20')
, các trường có liên quan của sự khác biệt đó sẽ giống như sau:
tm_mday = -19
tm_mon = 2
tm_year = 0
Bây giờ các trường phủ định được điều chỉnh. cho tm_mday
, mã trông như thế này:
while (tm->tm_mday < 0)
{
if (dt1 < dt2)
{
tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
tm->tm_mon--;
}
else
{
tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
tm->tm_mon--;
}
}
Kể từ dt1 > dt2
, else
nhánh được sử dụng và mã thêm số ngày trong tháng 5 (31) và giảm tháng đi 1, kết thúc bằng
tm_mday = 12
tm_mon = 1
tm_year = 0
Đó là kết quả bạn nhận được.
Thoạt nhìn, có vẻ như tm2->tm_mon
không phải là tháng thích hợp để chọn và tốt hơn nên lấy tháng trước của đối số bên trái:
day_tab[isleap(tm1->tm_year)][(tm1->tm_mon + 10) % 12]
Nhưng tôi không thể nói liệu lựa chọn đó có tốt hơn trong mọi trường hợp hay không và trong bất kỳ trường hợp nào, nhận xét này sẽ bồi thường cho chức năng, vì vậy tôi ngần ngại gọi đó là lỗi.
Bạn có thể muốn đưa nó vào danh sách gửi thư của tin tặc.