Skip to content

Commit bde8463

Browse files
committed
* **Fix:** Fixed 23.98, 29.97 DF, 29.97 NDF, 59.94 and 59.94 NDF rollover to 00:00:00:00 after 24 hours.
1 parent ab3de5e commit bde8463

3 files changed

Lines changed: 61 additions & 33 deletions

File tree

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
Changes
33
=======
44

5+
1.3.1
6+
=====
7+
8+
* **Fix:** Fixed 23.98, 29.97 DF, 29.97 NDF, 59.94 and 59.94 NDF rollover to ``00:00:00:00`` after 24 hours.
9+
510
1.3.0
611
=====
712

tests/test_timecode.py

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -418,30 +418,10 @@ def test_timecode_init_16(self):
418418
self.assertEqual('00:08:19:23', tc.__str__())
419419

420420
def test_timecode_init_17(self):
421-
tc = Timecode('29.97', frames=2589408)
422-
self.assertEqual('23:59:59;29', tc.__str__())
423-
424-
def test_timecode_init_18(self):
425-
tc = Timecode('29.97', frames=2589409)
426-
self.assertEqual('00:00:00;00', tc.__str__())
427-
428-
def test_timecode_init_19(self):
429-
tc = Timecode('29.97', frames=2589409, force_non_drop_frame=True)
430-
self.assertEqual('00:00:00:00', tc.__str__())
431-
432-
def test_timecode_init_20(self):
433-
tc = Timecode('59.94', frames=5178816)
434-
self.assertEqual('23:59:59;59', tc.__str__())
435-
436-
def test_timecode_init_21(self):
437-
tc = Timecode('59.94', frames=5178817)
438-
self.assertEqual('00:00:00;00', tc.__str__())
439-
440-
def test_timecode_init_22(self):
441421
tc = Timecode('25', 421729315)
442422
self.assertEqual('19:23:14:23', tc.__str__())
443423

444-
def test_timecode_init_23(self):
424+
def test_timecode_init_18(self):
445425
tc = Timecode('29.97', 421729315)
446426
self.assertEqual('19:23:14;23', tc.__str__())
447427
self.assertTrue(tc.drop_frame)
@@ -1214,9 +1194,13 @@ def test_op_overloads_mult_8(self):
12141194
tc3 = tc * tc2
12151195
tc4 = tc * 720
12161196
self.assertEqual(224121600, tc3._frames)
1217-
self.assertEqual("04:09:35:23", tc3.__str__())
1197+
self.assertEqual("01:59:59:23", tc3.__str__())
12181198
self.assertEqual(224121600, tc4._frames)
1219-
self.assertEqual("04:09:35:23", tc4.__str__())
1199+
self.assertEqual("01:59:59:23", tc4.__str__())
1200+
tc5 = Timecode('23.98', frames=311280 * 720) # should equal to this amount of frames
1201+
self.assertEqual("01:59:59:23", tc5.__str__())
1202+
tc5 = Timecode('23.98', frames=172800) # should equal to this amount of frames
1203+
self.assertEqual("01:59:59:23", tc5.__str__())
12201204

12211205
def test_op_overloads_mult_9(self):
12221206
tc = Timecode('ms', '03:36:09.230')
@@ -1725,3 +1709,44 @@ def test_fraction_lib_from_python3_raises_import_error_for_python2(self):
17251709
with mock.patch.dict(sys.modules, {'fractions': None}):
17261710
# the coverage should be now 100%
17271711
tc = Timecode('24')
1712+
1713+
def test_rollover_for_23_98(self):
1714+
"""test for bug report #33
1715+
"""
1716+
tc = Timecode('23.98', '23:58:47:00')
1717+
self.assertEqual(2071849, tc.frames)
1718+
tc.add_frames(24)
1719+
self.assertEqual(2071873, tc.frames)
1720+
self.assertEqual('23:58:48:00', tc.__repr__())
1721+
1722+
def test_rollover_for_29_97_1(self):
1723+
tc = Timecode('29.97', frames=2589408)
1724+
self.assertEqual('23:59:59;29', tc.__str__())
1725+
1726+
def test_rollover_for_29_97_2(self):
1727+
tc = Timecode('29.97', frames=2589409)
1728+
self.assertEqual('00:00:00;00', tc.__str__())
1729+
1730+
def test_rollover_for_29_97_3(self):
1731+
tc = Timecode('29.97', frames=2589409, force_non_drop_frame=True)
1732+
self.assertEqual('23:58:33:18', tc.__str__())
1733+
1734+
def test_rollover_for_29_97_4(self):
1735+
tc = Timecode('29.97', frames=2592001, force_non_drop_frame=True)
1736+
self.assertEqual('00:00:00:00', tc.__str__())
1737+
1738+
def test_rollover_for_59_94_DF_1(self):
1739+
tc = Timecode('59.94', frames=5178816)
1740+
self.assertEqual('23:59:59;59', tc.__str__())
1741+
1742+
def test_rollover_for_59_94_DF_2(self):
1743+
tc = Timecode('59.94', frames=5178817)
1744+
self.assertEqual('00:00:00;00', tc.__str__())
1745+
1746+
def test_rollover_for_59_94_NDF_1(self):
1747+
tc = Timecode('59.94', frames=5184000, force_non_drop_frame=True)
1748+
self.assertEqual('23:59:59:59', tc.__str__())
1749+
1750+
def test_rollover_for_59_94_NDF_2(self):
1751+
tc = Timecode('59.94', frames=5184001, force_non_drop_frame=True)
1752+
self.assertEqual('00:00:00:00', tc.__str__())

timecode/__init__.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2222
# THE SOFTWARE.
2323

24-
__version__ = '1.3.0'
24+
__version__ = '1.3.1'
2525

2626

2727
class Timecode(object):
@@ -126,7 +126,6 @@ def framerate(self, framerate): # lint:ok
126126
:param framerate:
127127
:return:
128128
"""
129-
130129
# Convert rational frame rate to float
131130
numerator = None
132131
denominator = None
@@ -260,21 +259,21 @@ def frames_to_tc(self, frames):
260259
261260
:returns str: the string representation of the current time code
262261
"""
263-
ffps = float(self.framerate)
264-
265262
if self.drop_frame:
266263
# Number of frames to drop on the minute marks is the nearest
267264
# integer to 6% of the framerate
265+
ffps = float(self.framerate)
268266
drop_frames = int(round(ffps * .066666))
269267
else:
268+
ffps = float(self._int_framerate)
270269
drop_frames = 0
271270

272-
# Number of frames in an hour
273-
frames_per_hour = int(round(ffps * 60 * 60))
274-
# Number of frames in a day - timecode rolls over after 24 hours
275-
frames_per_24_hours = frames_per_hour * 24
276271
# Number of frames per ten minutes
277272
frames_per_10_minutes = int(round(ffps * 60 * 10))
273+
274+
# Number of frames in a day - timecode rolls over after 24 hours
275+
frames_per_24_hours = int(round(ffps * 60 * 60 * 24))
276+
278277
# Number of frames per minute is the round of the framerate * 60 minus
279278
# the number of dropped frames
280279
frames_per_minute = int(round(ffps) * 60) - drop_frames
@@ -289,8 +288,7 @@ def frames_to_tc(self, frames):
289288
d = frame_number // frames_per_10_minutes
290289
m = frame_number % frames_per_10_minutes
291290
if m > drop_frames:
292-
frame_number += (drop_frames * 9 * d) + \
293-
drop_frames * ((m - drop_frames) // frames_per_minute)
291+
frame_number += (drop_frames * 9 * d) + drop_frames * ((m - drop_frames) // frames_per_minute)
294292
else:
295293
frame_number += drop_frames * 9 * d
296294

0 commit comments

Comments
 (0)