Django с postgresql, начальный 0 микросекунды datetime исчезает

#python #django #postgresql #datetime #psycopg2

Вопрос:

Я пытаюсь извлечь datetime типизированные данные из postgresql на django.

Но если микросекунда имеет начальное значение 0, как показано ниже

 |        datetime_field        |
|2021-06-07 09:22:13.099866 00 |
 

результат показан в виде

 datetime.datetime(2021, 6, 7, 9, 22, 13, 998660, tzinfo=<UTC>)
 

на языке Python.

Обратите внимание на микросекунду 099866. Он был изменен на 998660.

Если я вставлю полученный объект datetime без каких-либо изменений в postgresql, он будет загружен, как показано ниже.

 |        datetime_field        |
| 2021-06-07 09:22:13.99866 00 |
 

0 в начале исчезло.

Похоже, эта проблема связана с psycopg2, а не только с django, но я не могу найти никакого решения для этого.

Как я могу получить микросекунды во всей их полноте?

p.s. Добро пожаловать для редактирования только на английском языке. Поскольку я не говорю по-английски, я не уверен, правильно ли я написал выражения.


Добавление точного шага.

Я выполняю работу над контейнерами docker. Сейчас используются два контейнера, каждый для сервера django и сервера PostgreSQL.

 Version infos:
Python 3.9.1
Django==3.1.4
psycopg2==2.8.6
postgres (PostgreSQL) 13.1 (Debian 13.1-1.pgdg100 1)
 

Я тестирую с помощью клона производственной базы данных.

  1. ВЫБЕРИТЕ запрос для проблемных данных.
 TEST=# SELECT issued_at FROM table_name WHERE id = 153;
           issued_at
-------------------------------
 2021-06-18 10:10:49.075392 00
(1 row)
 
  1. В python manage.py shell , извлеките данные с помощью connections.cursor()
 >>> with transaction.atomic():
...     query = f'''SELECT issued_at FROM table_name WHERE id = 153;'''
...     with connections['test_db'].cursor() as cursor: 
...             cursor.execute(query)
...             print(cursor.fetchone())
...
(datetime.datetime(2021, 6, 18, 10, 10, 49, 753920, tzinfo=<UTC>),)
 

Дополнение 2.

Когда я получаю данные с помощью django Model.objects.get() , результат получается хорошим.

 >>> data = TableName.objects.get(id=153)
>>> data.issued_at
datetime.datetime(2021, 6, 18, 10, 10, 49, 75392, tzinfo=<UTC>)
 

Это кажется своего рода проблемой django.db.connections .

Комментарии:

1. Это похоже на потенциальную ошибку. Возможно, вы можете создать билет для этого: code.djangoproject.com/newticket

2. значения отправляются в базу данных в виде чисел, а не в виде строк. вы можете сохранить их в виде строки, а затем вставить.

3. @NikhilB: да, но дело в том, что чтение и запись должны быть обратными друг другу: если вы записываете некоторую метку времени в базу данных, вы ожидаете, что прочитаете то же значение обратно. Здесь это не так, что довольно странно .

4. @WillemVanOnsem Спасибо тебе. Я создам его, если окажется, что это ошибка. Сейчас я еще немного его тестирую.

5. Это был глупый вопрос. Я допустил ошибку при извлечении данных. Извините всех и спасибо за вашу любезную помощь.

Ответ №1:

Я этого не вижу:

 CREATE TABLE public.dt_test (
    id integer,
    ts_fld timestamp without time zone,
    tsz_fld timestamp with time zone
);
insert into dt_test values (1, '2021-06-07 09:22:13.099866 00', '2021-06-07 09:22:13.099866 00');
insert into dt_test values (2, '2021-06-07 09:22:13.99866 00', '2021-06-07 09:22:13.99866 00');
select * from dt_test ;
 id |           ts_fld           |            tsz_fld            
---- ---------------------------- -------------------------------
  1 | 2021-06-07 09:22:13.099866 | 2021-06-07 02:22:13.099866-07
  2 | 2021-06-07 09:22:13.99866  | 2021-06-07 02:22:13.99866-07

import psycopg2 
cur.execute('select * from dt_test')
rs = cur.fetchall()
rs                                                                                                                                                                        
Out[23]: 
[(1,
  datetime.datetime(2021, 6, 7, 9, 22, 13, 99866),
  datetime.datetime(2021, 6, 7, 2, 22, 13, 99866, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=-420, name=None))),
 (2,
  datetime.datetime(2021, 6, 7, 9, 22, 13, 998660),
  datetime.datetime(2021, 6, 7, 2, 22, 13, 998660, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=-420, name=None)))]
cur.execute('insert into dt_test(id, ts_fld) values(%s, %s)', [3, datetime.datetime(2021, 6, 7, 9, 22, 13, 99866)])
con.commit()
 select * from dt_test ;
 id |           ts_fld           |            tsz_fld            
---- ---------------------------- -------------------------------
  1 | 2021-06-07 09:22:13.099866 | 2021-06-07 02:22:13.099866-07
  2 | 2021-06-07 09:22:13.99866  | 2021-06-07 02:22:13.99866-07
  3 | 2021-06-07 09:22:13.099866 | NULL
 

То, что вы видите, — это нормализация до 1000000:

 select 998660/1000000.0;
        ?column?        
------------------------
 0.99866000000000000000

select 99866/1000000.0;
        ?column?        
------------------------
 0.09986600000000000000
 

Комментарии:

1. Вау… извини, что я неправильно понял это. Спасибо, я попробую еще раз.

2. Хм, кажется, с моим тестом все немного по-другому. Могу я получить информацию о вашей версии? Я тестирую на postgres v13.1. postgres (PostgreSQL) 13.1 (Debian 13.1-1.pgdg100 1) , Django==3.1.4 и psycopg2==2.8.6 .

3. Я пробовал с psycopg2 2.8.5 and 2.91 и. postgres 12.7 and 13.0 Я получаю те же результаты. Добавьте в свой вопрос точные шаги, которые вы предпринимаете в своем тесте, и возвращаемые результаты. На данный момент я бы оставил Django это в стороне . Также добавьте Python версию, которую вы используете.

4. Это Python 3.9.1 . Я изменил вопрос. Похоже django.db.connections , с объектом что-то не так.

5. Я нахожу, что в это трудно поверить, так как основной драйвер один и тот же, и это та часть, которая выполняет преобразование типов. Вы уверены connections['test_db'] , что на самом деле указываете на то, что вы думаете?