age
timestamptz_age
. द्वारा गणना की जाती है src/backend/utils/adt/timestamp.c
में कार्य करें . टिप्पणी कहती है:
/* 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.
*/
कोड पहले तर्कों को struct pg_tm
. में परिवर्तित करता है चर tm1
और tm2
(struct pg_tm
C लाइब्रेरी के struct tm
. के समान है , लेकिन अतिरिक्त समय क्षेत्र फ़ील्ड हैं) और फिर अंतर की गणना करता है tm
प्रति फ़ील्ड।
age('2018-07-01','2018-05-20')
. के मामले में , उस अंतर के प्रासंगिक क्षेत्र इस तरह दिखाई देंगे:
tm_mday = -19
tm_mon = 2
tm_year = 0
अब नकारात्मक क्षेत्रों को समायोजित किया जाता है। tm_mday
. के लिए , कोड इस तरह दिखता है:
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--;
}
}
चूंकि dt1 > dt2
, else
शाखा ली जाती है, और कोड मई (31) में दिनों की संख्या जोड़ता है और महीने को 1 से कम करता है, जिसके साथ समाप्त होता है
tm_mday = 12
tm_mon = 1
tm_year = 0
आपको यही परिणाम मिलता है।
अब पहली नज़र में ऐसा लगता है कि tm2->tm_mon
चुनने के लिए सही महीना नहीं है, और बाएं तर्क के पिछले महीने को लेना बेहतर होता:
day_tab[isleap(tm1->tm_year)][(tm1->tm_mon + 10) % 12]
लेकिन मैं यह नहीं कह सकता कि क्या वह विकल्प सभी मामलों में बेहतर होगा, और किसी भी घटना में टिप्पणी समारोह की क्षतिपूर्ति करती है, इसलिए मैं इसे एक बग कहने में संकोच करूंगा।
हो सकता है कि आप इसे हैकर्स की मेलिंग सूची के साथ उठाना चाहें।