-
Notifications
You must be signed in to change notification settings - Fork 301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How can I fix TypeError: can't compare offset-naive and offset-aware datetimes #630
Comments
Hm this might be a bug in Flask-Restless, I'll look into it. Here is a failing test case that I will add to def test_updating_aware_datetime(self):
# GitHub issue #630.
now = datetime.now(tz=timezone.utc)
person = self.Person(id=1, birth_datetime=now)
self.session.add(person)
self.session.commit()
later = datetime.now(tz=timezone.utc)
data = {
'data': {
'type': 'person',
'id': '1',
'attributes': {
'birth_datetime': later.isoformat()
}
}
}
response = self.app.patch('/api/person/1', data=dumps(data))
print(response.data)
self.assertEqual(response.status_code, 204)
self.assertEqual(person.birth_datetime, later) |
Actually, I believe this is a problem with the backend. Depending on your database, you may not have timezone support (or even datetime type support). I'm not sure what your database backend is, but you may try setting the For example, in my unit tests, since I am using SQLite, even if I set now = datetime.now(tz=timezone.utc)
person = self.Person(id=1, birth_datetime=now)
self.session.add(person)
self.session.commit()
print(now)
# 2017-02-06 05:00:49.657781+00:00
print(person.birth_datetime)
# 2017-02-06 05:00:49.657781 So are you certain you have support for timezones in your database backend? |
I'm using SQL Server, the |
What I'm saying is that your client is making a request to set a datetime field with a timezone-aware object; the "Z" in the datetime object in your original example indicates timezone-aware: >>> from dateutil.parser import parse
>>> parse('2017-01-24T06:00:00.000Z')
datetime.datetime(2017, 1, 24, 6, 0, tzinfo=tzutc())
>>> parse('2017-01-24T06:00:00.000')
datetime.datetime(2017, 1, 24, 6, 0) However, your database is timezone-naive, like in the second print statement in my example code above: print(now)
# 2017-02-06 05:00:49.657781+00:00
print(person.birth_datetime)
# 2017-02-06 05:00:49.657781 So the request is a timezone-aware object, but the database is timezone-naive. There is a mismatch, and therefore SQLAlchemy raises an exception. None of this has anything to do with Flask-Restless except for the fact that we correctly parse your timezone-aware datetime from the string in the body of the request. I will add a test that ensures a meaningful error message is sent to the client when this happens, but other than that, I'm going to mark this is as "not a bug". |
Actually, the test I wrote in #630 (comment) doesn't demonstrate cause the |
I'll work on a minimal example. Here's an update, I think this might have something to do with the issue. It also explains why I am so confused. One server PATCH requests are working correctly, the other is not, despite using the same code.
My overall workflow is the object is retrieved via GET, edited in a form, and then submitted back to flask restless via PATCH. On the GET request, each server returns the object, but there is a discrepancy between the two in one of the date field, even though the data is the same.
On the PATCH request:
Could that have something to do with the issue? |
Okay, here's a minimal example: Created a table with id and date field: import flask
import flask_sqlalchemy
import flask_restless
app = flask.Flask(__name__)
app.config['DEBUG'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'mssql+pyodbc://gis'
db = flask_sqlalchemy.SQLAlchemy(app)
class DateTest(db.Model):
__table_args__ = {'schema':'dbo'}
__tablename__ = 'test_date_bug'
id = db.Column(db.Integer, primary_key=True)
some_date = db.Column(db.DateTime,)
manager = flask_restless.APIManager(app, flask_sqlalchemy_db=db)
manager.create_api(DateTest, methods=['GET', 'POST', 'DELETE', 'PATCH'])
app.run(host='0.0.0.0') POST /api/test_date_bug
{"data":{"attributes":{"some_date":"2017-02-28T08:10:30.497Z"},"type":"test_date_bug"}}
RESULT
{
"data": {
"attributes": {
"some_date": "2017-02-28T08:10:30.497000+00:00"
},
"id": "9",
"links": {
"self": "/api/test_date_bug/9"
},
"type": "test_date_bug"
},
"included": [],
"jsonapi": {
"version": "1.0"
},
"links": {},
"meta": {}
}
GET /api/test_date_bug/9
{
"data": {
"attributes": {
"some_date": "2017-02-28T08:10:30.497000"
},
"id": "9",
"links": {
"self": "/api/test_date_bug/9"
},
"type": "test_date_bug"
},
"included": [],
"jsonapi": {
"version": "1.0"
},
"links": {
"self": "/api/test_date_bug/9"
},
"meta": {}
} PATCH /api/test_date_bug/9
{"data":{"attributes":{"some_date":"2017-02-28T08:10:30.497000+00:00"},"type":"test_date_bug","id":"9"}}
Results in error. I think since the data is not timezone aware, flask restless should not return timezone aware dates in the POST and GET requests |
Thanks for the example, I'll take a look at this. |
Let's deal with each request individually.
What can we do about this (item 4)? I'm not sure. I don't want Flask-Restless to catch every possible type of error that might be raised (it's already catching essentially all SQLAlchemy exceptions). I'm not sure there's anything I can do about this. As a workaround, you can use a preprocessor to strip the timezones from the incoming requests. As for your earlier comment about different versions of Python producing different versions of datetime strings, I'm guessing you are using $ python2 -c "from datetime import datetime; now = datetime.now(); print(now); print(now.isoformat())"
2017-03-25 00:08:04.802940
2017-03-25T00:08:04.802940 So again that is not a Flask-Restless issue. |
I have created a pull request #647 to fix item 2 in my list above. |
@jfinkels sounds good. Thanks for taking a look |
Running into this issue if I have a model like this:
And I send a request to flask-restless like this:
PATCH /api/plan_index/3936
It only happens once there is a value set on that column. If the value is null, and I set a new datetime, the PATCH is successful.
Also, posting new features with values is successful. It is only updating existing datetime values.
I'm not sure if this is a problem with flask-restless or not, but it seems that flask-restless is the first logical step to solving it.
My data is in sql server, and some of the values look like this:
The column type in sql server is
datetime
.The text was updated successfully, but these errors were encountered: