Video.get_date_taken()   F
last analyzed

↳ Parent: Video

Complexity

Conditions 11

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 47

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 11
c 2
b 0
f 0
dl 0
loc 47
rs 3.1764

How to fix   Complexity   

Complexity

Complex classes like Video.get_date_taken() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""
2
The video module contains the :class:`Video` class, which represents video
3
objects (AVI, MOV, etc.).
4
5
.. moduleauthor:: Jaisen Mathai <[email protected]>
6
"""
7
from __future__ import print_function
8
from __future__ import absolute_import
9
from __future__ import division
10
11
# load modules
12
from datetime import datetime
13
14
import os
15
import re
16
import time
17
18
from .media import Media
19
20
21
class Video(Media):
22
23
    """A video object.
24
25
    :param str source: The fully qualified path to the video file.
26
    """
27
28
    __name__ = 'Video'
29
30
    #: Valid extensions for video files.
31
    extensions = ('avi', 'm4v', 'mov', 'mp4', 'mpg', 'mpeg', '3gp')
32
33
    def __init__(self, source=None):
34
        super(Video, self).__init__(source)
35
        self.exif_map['date_taken'] = [
36
            'QuickTime:CreationDate',
37
            'QuickTime:CreationDate-und-US',
38
            'QuickTime:MediaCreateDate'
39
        ]
40
        self.title_key = 'XMP:DisplayName'
41
        self.latitude_keys = [
42
            'XMP:GPSLatitude',
43
            # 'QuickTime:GPSLatitude',
44
            'Composite:GPSLatitude'
45
        ]
46
        self.longitude_keys = [
47
            'XMP:GPSLongitude',
48
            # 'QuickTime:GPSLongitude',
49
            'Composite:GPSLongitude'
50
        ]
51
        self.latitude_ref_key = 'EXIF:GPSLatitudeRef'
52
        self.longitude_ref_key = 'EXIF:GPSLongitudeRef'
53
        self.set_gps_ref = False
54
55
    def get_date_taken(self):
56
        """Get the date which the photo was taken.
57
58
        The date value returned is defined by the min() of mtime and ctime.
59
60
        :returns: time object or None for non-photo files or 0 timestamp
61
        """
62
        if(not self.is_valid()):
63
            return None
64
65
        source = self.source
66
        seconds_since_epoch = min(os.path.getmtime(source), os.path.getctime(source))  # noqa
67
68
        exif = self.get_exiftool_attributes()
69
        for date_key in self.exif_map['date_taken']:
70
            if date_key in exif:
71
                # Example date strings we want to parse
72
                # 2015:01:19 12:45:11-08:00
73
                # 2013:09:30 07:06:05
74
                date = re.search('([0-9: ]+)([-+][0-9:]+)?', exif[date_key])
75
                if(date is not None):
76
                    date_string = date.group(1)
77
                    date_offset = date.group(2)
78
                    try:
79
                        exif_seconds_since_epoch = time.mktime(
80
                            datetime.strptime(
81
                                date_string,
82
                                '%Y:%m:%d %H:%M:%S'
83
                            ).timetuple()
84
                        )
85
                        if(exif_seconds_since_epoch < seconds_since_epoch):
86
                            seconds_since_epoch = exif_seconds_since_epoch
87
                            if date_offset is not None:
88
                                offset_parts = date_offset[1:].split(':')
89
                                offset_seconds = int(offset_parts[0]) * 3600
90
                                offset_seconds = offset_seconds + int(offset_parts[1]) * 60  # noqa
91
                                if date_offset[0] == '-':
92
                                    seconds_since_epoch - offset_seconds
93
                                elif date_offset[0] == '+':
94
                                    seconds_since_epoch + offset_seconds
95
                    except:
96
                        pass
97
98
        if(seconds_since_epoch == 0):
99
            return None
100
101
        return time.gmtime(seconds_since_epoch)
102