PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Fungsi PostgreSQL age():hasil yang berbeda/tidak terduga saat mendarat di bulan yang berbeda

age dihitung dengan timestamptz_age fungsi di src/backend/utils/adt/timestamp.c . Komentarnya berbunyi:

/* 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.
 */

Kode pertama-tama mengubah argumen menjadi struct pg_tm variabel tm1 dan tm2 (struct pg_tm mirip dengan struct tm perpustakaan C , tetapi memiliki bidang zona waktu tambahan) dan kemudian menghitung perbedaan tm per bidang.

Dalam kasus age('2018-07-01','2018-05-20') , bidang yang relevan dari perbedaan itu akan terlihat seperti ini:

tm_mday = -19
tm_mon  =   2
tm_year =   0

Sekarang bidang negatif disesuaikan. untuk tm_mday , kodenya terlihat seperti ini:

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--;
    }
}

Sejak dt1 > dt2 , else cabang diambil, dan kode menambahkan jumlah hari di bulan Mei (31) dan mengurangi bulan sebanyak 1, berakhir dengan

tm_mday = 12
tm_mon  =  1
tm_year =  0

Itulah hasil yang Anda dapatkan.

Sekarang pada pandangan pertama tampaknya tm2->tm_mon bukan bulan yang tepat untuk dipilih, dan akan lebih baik untuk mengambil bulan sebelumnya dari argumen kiri:

day_tab[isleap(tm1->tm_year)][(tm1->tm_mon + 10) % 12]

Tetapi saya tidak dapat mengatakan apakah pilihan itu akan lebih baik dalam semua kasus, dan bagaimanapun juga, komentar tersebut mengganti kerugian fungsi tersebut, jadi saya ragu untuk menyebutnya sebagai bug.

Anda mungkin ingin membawanya ke milis peretas.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. postgres ke MS Access

  2. Tambahkan kolom kenaikan otomatis ke tabel yang ada yang dipesan berdasarkan tanggal

  3. Memperbaiki tabel TOAST yang rusak

  4. Rails + Postgres:Tidak mengembalikan info zona waktu pada kolom dari tabel yang digabungkan

  5. Tipe Data PostgreSQL dan C#