Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
ae6fa914
Kaydet (Commit)
ae6fa914
authored
Ara 28, 2017
tarafından
Sergey Fedoseev
Kaydeden (comit)
Tim Graham
Ara 28, 2017
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #28926 -- Fixed loss of precision of big DurationField values on SQLite and MySQL.
üst
46d1af2e
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
47 additions
and
7 deletions
+47
-7
operations.py
django/db/backends/mysql/operations.py
+2
-1
base.py
django/db/backends/sqlite3/base.py
+2
-1
__init__.py
django/db/models/fields/__init__.py
+2
-3
duration.py
django/utils/duration.py
+4
-0
tests.py
tests/expressions/tests.py
+19
-0
test_durationfield.py
tests/model_fields/test_durationfield.py
+1
-1
test_duration.py
tests/utils_tests/test_duration.py
+17
-1
No files found.
django/db/backends/mysql/operations.py
Dosyayı görüntüle @
ae6fa914
...
@@ -3,6 +3,7 @@ import uuid
...
@@ -3,6 +3,7 @@ import uuid
from
django.conf
import
settings
from
django.conf
import
settings
from
django.db.backends.base.operations
import
BaseDatabaseOperations
from
django.db.backends.base.operations
import
BaseDatabaseOperations
from
django.utils
import
timezone
from
django.utils
import
timezone
from
django.utils.duration
import
duration_microseconds
from
django.utils.encoding
import
force_text
from
django.utils.encoding
import
force_text
...
@@ -105,7 +106,7 @@ class DatabaseOperations(BaseDatabaseOperations):
...
@@ -105,7 +106,7 @@ class DatabaseOperations(BaseDatabaseOperations):
return
"TIME(
%
s)"
%
(
field_name
)
return
"TIME(
%
s)"
%
(
field_name
)
def
date_interval_sql
(
self
,
timedelta
):
def
date_interval_sql
(
self
,
timedelta
):
return
"INTERVAL '
%06
f' SECOND_MICROSECOND"
%
timedelta
.
total_seconds
(
)
return
'INTERVAL
%
s MICROSECOND'
%
duration_microseconds
(
timedelta
)
def
format_for_duration_arithmetic
(
self
,
sql
):
def
format_for_duration_arithmetic
(
self
,
sql
):
return
'INTERVAL
%
s MICROSECOND'
%
sql
return
'INTERVAL
%
s MICROSECOND'
%
sql
...
...
django/db/backends/sqlite3/base.py
Dosyayı görüntüle @
ae6fa914
...
@@ -17,6 +17,7 @@ from django.utils import timezone
...
@@ -17,6 +17,7 @@ from django.utils import timezone
from
django.utils.dateparse
import
(
from
django.utils.dateparse
import
(
parse_date
,
parse_datetime
,
parse_duration
,
parse_time
,
parse_date
,
parse_datetime
,
parse_duration
,
parse_time
,
)
)
from
django.utils.duration
import
duration_microseconds
from
.client
import
DatabaseClient
# isort:skip
from
.client
import
DatabaseClient
# isort:skip
from
.creation
import
DatabaseCreation
# isort:skip
from
.creation
import
DatabaseCreation
# isort:skip
...
@@ -471,7 +472,7 @@ def _sqlite_time_diff(lhs, rhs):
...
@@ -471,7 +472,7 @@ def _sqlite_time_diff(lhs, rhs):
def
_sqlite_timestamp_diff
(
lhs
,
rhs
):
def
_sqlite_timestamp_diff
(
lhs
,
rhs
):
left
=
backend_utils
.
typecast_timestamp
(
lhs
)
left
=
backend_utils
.
typecast_timestamp
(
lhs
)
right
=
backend_utils
.
typecast_timestamp
(
rhs
)
right
=
backend_utils
.
typecast_timestamp
(
rhs
)
return
(
left
-
right
)
.
total_seconds
()
*
1000000
return
duration_microseconds
(
left
-
right
)
def
_sqlite_regexp
(
re_pattern
,
re_string
):
def
_sqlite_regexp
(
re_pattern
,
re_string
):
...
...
django/db/models/fields/__init__.py
Dosyayı görüntüle @
ae6fa914
...
@@ -24,7 +24,7 @@ from django.utils.datastructures import DictWrapper
...
@@ -24,7 +24,7 @@ from django.utils.datastructures import DictWrapper
from
django.utils.dateparse
import
(
from
django.utils.dateparse
import
(
parse_date
,
parse_datetime
,
parse_duration
,
parse_time
,
parse_date
,
parse_datetime
,
parse_duration
,
parse_time
,
)
)
from
django.utils.duration
import
duration_string
from
django.utils.duration
import
duration_
microseconds
,
duration_
string
from
django.utils.encoding
import
force_bytes
,
smart_text
from
django.utils.encoding
import
force_bytes
,
smart_text
from
django.utils.functional
import
Promise
,
cached_property
from
django.utils.functional
import
Promise
,
cached_property
from
django.utils.ipv6
import
clean_ipv6_address
from
django.utils.ipv6
import
clean_ipv6_address
...
@@ -1617,8 +1617,7 @@ class DurationField(Field):
...
@@ -1617,8 +1617,7 @@ class DurationField(Field):
return
value
return
value
if
value
is
None
:
if
value
is
None
:
return
None
return
None
# Discard any fractional microseconds due to floating point arithmetic.
return
duration_microseconds
(
value
)
return
round
(
value
.
total_seconds
()
*
1000000
)
def
get_db_converters
(
self
,
connection
):
def
get_db_converters
(
self
,
connection
):
converters
=
[]
converters
=
[]
...
...
django/utils/duration.py
Dosyayı görüntüle @
ae6fa914
...
@@ -38,3 +38,7 @@ def duration_iso_string(duration):
...
@@ -38,3 +38,7 @@ def duration_iso_string(duration):
days
,
hours
,
minutes
,
seconds
,
microseconds
=
_get_duration_components
(
duration
)
days
,
hours
,
minutes
,
seconds
,
microseconds
=
_get_duration_components
(
duration
)
ms
=
'.{:06d}'
.
format
(
microseconds
)
if
microseconds
else
""
ms
=
'.{:06d}'
.
format
(
microseconds
)
if
microseconds
else
""
return
'{}P{}DT{:02d}H{:02d}M{:02d}{}S'
.
format
(
sign
,
days
,
hours
,
minutes
,
seconds
,
ms
)
return
'{}P{}DT{:02d}H{:02d}M{:02d}{}S'
.
format
(
sign
,
days
,
hours
,
minutes
,
seconds
,
ms
)
def
duration_microseconds
(
delta
):
return
(
24
*
60
*
60
*
delta
.
days
+
delta
.
seconds
)
*
1000000
+
delta
.
microseconds
tests/expressions/tests.py
Dosyayı görüntüle @
ae6fa914
...
@@ -1250,6 +1250,16 @@ class FTimeDeltaTests(TestCase):
...
@@ -1250,6 +1250,16 @@ class FTimeDeltaTests(TestCase):
]
]
self
.
assertEqual
(
over_estimate
,
[
'e4'
])
self
.
assertEqual
(
over_estimate
,
[
'e4'
])
@skipUnlessDBFeature
(
'supports_temporal_subtraction'
)
def
test_datetime_subtraction_microseconds
(
self
):
delta
=
datetime
.
timedelta
(
microseconds
=
8999999999999999
)
Experiment
.
objects
.
update
(
end
=
F
(
'start'
)
+
delta
)
qs
=
Experiment
.
objects
.
annotate
(
delta
=
ExpressionWrapper
(
F
(
'end'
)
-
F
(
'start'
),
output_field
=
models
.
DurationField
())
)
for
e
in
qs
:
self
.
assertEqual
(
e
.
delta
,
delta
)
def
test_duration_with_datetime
(
self
):
def
test_duration_with_datetime
(
self
):
# Exclude e1 which has very high precision so we can test this on all
# Exclude e1 which has very high precision so we can test this on all
# backends regardless of whether or not it supports
# backends regardless of whether or not it supports
...
@@ -1259,6 +1269,15 @@ class FTimeDeltaTests(TestCase):
...
@@ -1259,6 +1269,15 @@ class FTimeDeltaTests(TestCase):
)
.
order_by
(
'name'
)
)
.
order_by
(
'name'
)
self
.
assertQuerysetEqual
(
over_estimate
,
[
'e3'
,
'e4'
,
'e5'
],
lambda
e
:
e
.
name
)
self
.
assertQuerysetEqual
(
over_estimate
,
[
'e3'
,
'e4'
,
'e5'
],
lambda
e
:
e
.
name
)
def
test_duration_with_datetime_microseconds
(
self
):
delta
=
datetime
.
timedelta
(
microseconds
=
8999999999999999
)
qs
=
Experiment
.
objects
.
annotate
(
dt
=
ExpressionWrapper
(
F
(
'start'
)
+
delta
,
output_field
=
models
.
DateTimeField
(),
))
for
e
in
qs
:
self
.
assertEqual
(
e
.
dt
,
e
.
start
+
delta
)
def
test_date_minus_duration
(
self
):
def
test_date_minus_duration
(
self
):
more_than_4_days
=
Experiment
.
objects
.
filter
(
more_than_4_days
=
Experiment
.
objects
.
filter
(
assigned__lt
=
F
(
'completed'
)
-
Value
(
datetime
.
timedelta
(
days
=
4
),
output_field
=
models
.
DurationField
())
assigned__lt
=
F
(
'completed'
)
-
Value
(
datetime
.
timedelta
(
days
=
4
),
output_field
=
models
.
DurationField
())
...
...
tests/model_fields/test_durationfield.py
Dosyayı görüntüle @
ae6fa914
...
@@ -12,7 +12,7 @@ from .models import DurationModel, NullDurationModel
...
@@ -12,7 +12,7 @@ from .models import DurationModel, NullDurationModel
class
TestSaveLoad
(
TestCase
):
class
TestSaveLoad
(
TestCase
):
def
test_simple_roundtrip
(
self
):
def
test_simple_roundtrip
(
self
):
duration
=
datetime
.
timedelta
(
days
=
123
,
seconds
=
123
,
microseconds
=
123
)
duration
=
datetime
.
timedelta
(
microseconds
=
8999999999999999
)
DurationModel
.
objects
.
create
(
field
=
duration
)
DurationModel
.
objects
.
create
(
field
=
duration
)
loaded
=
DurationModel
.
objects
.
get
()
loaded
=
DurationModel
.
objects
.
get
()
self
.
assertEqual
(
loaded
.
field
,
duration
)
self
.
assertEqual
(
loaded
.
field
,
duration
)
...
...
tests/utils_tests/test_duration.py
Dosyayı görüntüle @
ae6fa914
...
@@ -2,7 +2,9 @@ import datetime
...
@@ -2,7 +2,9 @@ import datetime
import
unittest
import
unittest
from
django.utils.dateparse
import
parse_duration
from
django.utils.dateparse
import
parse_duration
from
django.utils.duration
import
duration_iso_string
,
duration_string
from
django.utils.duration
import
(
duration_iso_string
,
duration_microseconds
,
duration_string
,
)
class
TestDurationString
(
unittest
.
TestCase
):
class
TestDurationString
(
unittest
.
TestCase
):
...
@@ -79,3 +81,17 @@ class TestParseISODurationRoundtrip(unittest.TestCase):
...
@@ -79,3 +81,17 @@ class TestParseISODurationRoundtrip(unittest.TestCase):
def
test_negative
(
self
):
def
test_negative
(
self
):
duration
=
datetime
.
timedelta
(
days
=-
1
,
hours
=
1
,
minutes
=
3
,
seconds
=
5
)
duration
=
datetime
.
timedelta
(
days
=-
1
,
hours
=
1
,
minutes
=
3
,
seconds
=
5
)
self
.
assertEqual
(
parse_duration
(
duration_iso_string
(
duration
))
.
total_seconds
(),
duration
.
total_seconds
())
self
.
assertEqual
(
parse_duration
(
duration_iso_string
(
duration
))
.
total_seconds
(),
duration
.
total_seconds
())
class
TestDurationMicroseconds
(
unittest
.
TestCase
):
def
test
(
self
):
deltas
=
[
datetime
.
timedelta
.
max
,
datetime
.
timedelta
.
min
,
datetime
.
timedelta
.
resolution
,
-
datetime
.
timedelta
.
resolution
,
datetime
.
timedelta
(
microseconds
=
8999999999999999
),
]
for
delta
in
deltas
:
with
self
.
subTest
(
delta
=
delta
):
self
.
assertEqual
(
datetime
.
timedelta
(
microseconds
=
duration_microseconds
(
delta
)),
delta
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment