pyodbc icon indicating copy to clipboard operation
pyodbc copied to clipboard

Error on DB2 time fields that are 24:00:00

Open dkornacki-cutco opened this issue 3 years ago • 5 comments

Environment

  • Python: 3.8
  • pyodbc: 4.0.31
  • OS: Windows
  • DB: Db2 for i 7.4
  • Driver: iAccess Client Solutions

Issue

Time fields that are 24:00:00 are throwing ValueError: hour must be in 0..23. Datetime fields were fixed in #783 for #782 but there was an oversight on time-only fields. A similar fix is needed.

dkornacki-cutco avatar Aug 05 '21 19:08 dkornacki-cutco

The only two fixes I can think of are:

Convert to 00:00. Technically 24:00 is 00:00, just on the next day. This could be surprising if there is an associated date, either explicit or implicit. You would not be able to tell if the original value was 00:00 or 24:00.

Convert to 23:59.999999. This may cause round-trip confusion.

What would you expect the fix to do?

mkleehammer avatar Aug 22 '21 19:08 mkleehammer

Converting 24:00 to 00:00 and incrementing the day is commonly how this is handled. I think that is the best solution here.

dkornacki-cutco avatar Aug 24 '21 19:08 dkornacki-cutco

Incrementing the day only makes sense if the value in the db has a date. Python does not support a time instance with .hour >= 24.

Possibly a timedelta instance could be created. Unfortunately, the correlation between a SQL type and the Python type that pyodbc returns is very strong and not configurable, likely due to the DBAPI spec that pyodbc implements.

What about raising an exception where one of the args is a timedelta instance with the exact hours+minutes+seconds as read from the db? This would show that this is still not a "happy-path" way of doing things, but would allow trapping for the exception and handling the value.

soundstripe avatar Nov 29 '21 13:11 soundstripe

Would it be possible to check if the received value from the field with time is larger than 24 hours before it gets assigned to a datetime.time object and use the datetime.timedelta instead?

I have an issue with the TIME datatype in MySQL. Everything over 24 hours gets removed. For example, "124:13:35" converts into"4:13:35": image

janipez avatar Feb 25 '22 12:02 janipez

For MySQL, mysqlclient already returns a datetime.timedelta object:

import sqlalchemy as sa

connection_url = "mysql+mysqldb://scott:tiger@localhost:3307/mydb"
engine = sa.create_engine(connection_url)
with engine.begin() as conn:
    result = conn.exec_driver_sql("SELECT CAST('124:13:35' AS TIME(0))").scalar()
    print(result)  # 5 days, 4:13:35
    print(repr(result))  # datetime.timedelta(days=5, seconds=15215)
    result = conn.exec_driver_sql("SELECT CAST('4:13:35' AS TIME(0))").scalar()
    print(result)  # 4:13:35
    print(repr(result))  # datetime.timedelta(seconds=15215)

Many, many SQLAlchemy users have found that using mysqlclient (or PyMySQL) works better than using MySQL Connector/ODBC.

gordthompson avatar Aug 16 '22 14:08 gordthompson