Issues (1445)

pincer/utils/timestamp.py (19 issues)

1
# Copyright Pincer 2021-Present
0 ignored issues
show
Missing module docstring
Loading history...
2
# Full MIT License can be found in `LICENSE` at the project root.
3
4
from __future__ import annotations
5
6
from datetime import datetime
7
from typing import Optional, TypeVar, Union
8
9
DISCORD_EPOCH = 1420070400
10
TS = TypeVar("TS", str, datetime, float, int)
11
12
13
class Timestamp:
14
    """Contains a lot of useful methods for working with timestamps.
15
16
    Attributes
17
    ----------
18
    date: :class:`str`
19
        The time of the timestamp.
20
    time: :class:`str`
21
        Alias for date.
22
23
    Parameters
24
    ----------
25
    time: Union[:class:`str`, :class:`int`, :class:`float`, :class:`datetime.datetime`]
26
    """
27
28
    # noqa: E501
29
30
    def __init__(self, time: Optional[TS] = None):
31
        self.__time = Timestamp.parse(time)
32
        self.__epoch = Timestamp.to_epoch(self.__time)
33
        self.date, self.time = str(self).split()
34
35
    @classmethod
36
    def __factory__(cls, time: Optional[TS] = None) -> datetime:
37
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
38
        """
39
40
        Parameters
41
        ----------
42
        time
43
44
        Returns
45
        -------
46
47
        """
48
        return cls.parse(time)
49
50
    @staticmethod
51
    def to_epoch(time: datetime) -> int:
52
        """Convert a datetime to an epoch.
53
54
        time: :class:`datetime.datetime`
55
            The datetime to convert.
56
57
        Returns
58
        -------
59
        :class:`int`:
60
            The epoch time integer.
61
        """
62
        return int(time.timestamp() * 1000)
63
64
    @staticmethod
65
    def string_to_datetime(string: str) -> datetime:
66
        """Convert a string to a datetime object.
67
68
        string: :class:`str`
69
            The string to convert.
70
71
        Returns
72
        -------
73
        :class:`datetime.datetime`:
74
            The converted datetime object.
75
        """
76
        return datetime.fromisoformat(string)
77
78
    @staticmethod
79
    def epoch_to_datetime(epoch: Union[int, float]) -> datetime:
80
        """Convert an epoch to a datetime object.
81
82
        epoch: Union[:class:`int`, :class:`float`]
83
            The epoch to convert to a datetime object.
84
85
        Returns
86
        -------
87
        :class:`datetime.datetime`:
88
            The converted datetime object.
89
        """
90
        return datetime.utcfromtimestamp(epoch)
91
92
    @staticmethod
93
    def parse(time: Optional[TS] = None) -> datetime:
94
        """Convert a time to datetime object.
95
96
        time: Optional[Union[:class:`str`, :class:`int`, :class:`float`, :class:`datetime.datetime`]]
0 ignored issues
show
This line is too long as per the coding-style (101/100).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
97
            The time to be converted to a datetime object.
98
            This can be one of these types: datetime, float, int, str
99
100
            If no parameter is passed it will return the current
101
            datetime.
102
103
        Returns
104
        -------
105
        :class:`datetime.datetime`:
106
            The converted datetime object.
107
        """
108
        # noqa: E501
109
110
        if isinstance(time, datetime):
0 ignored issues
show
Unnecessary "elif" after "return"
Loading history...
111
            return time
112
113
        elif isinstance(time, str):
114
            return Timestamp.string_to_datetime(time)
115
116
        elif isinstance(time, (int, float)):
117
            dt = Timestamp.epoch_to_datetime(t := int(time))
118
119
            if dt.year < 2015:  # if not Discord Epoch
120
                t += DISCORD_EPOCH  # make it Unix Epoch
121
            return Timestamp.epoch_to_datetime(t)
122
123
        return datetime.now()
124
125
    def __getattr__(self, key: str) -> int:
126
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
127
        """
128
129
        Parameters
130
        ----------
131
        key
132
133
        Returns
134
        -------
135
136
        """
137
        return getattr(self.__time, key)
138
139
    def __str__(self) -> str:
140
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
141
        """
142
143
        Returns
144
        -------
145
146
        """
147
        if len(string := str(self.__time)) == 19:
148
            return string + ".000"
149
        return string[:-3]
150
151
    def __int__(self) -> int:
152
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
153
        """
154
155
        Returns
156
        -------
157
158
        """
159
        return self.__epoch  # in milliseconds
160
161
    def __float__(self) -> float:
162
        """
163
164
        Returns
165
        -------
166
167
        """
168
        return self.__epoch / 1000  # in seconds
169
170
    def __ge__(self, other: Timestamp) -> bool:
171
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
172
        """
173
174
        Parameters
175
        ----------
176
        other
177
178
        Returns
179
        -------
180
181
        """
182
        return self.__epoch >= other.__epoch
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like __epoch was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
183
184
    def __gt__(self, other: Timestamp) -> bool:
185
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
186
        """
187
188
        Parameters
189
        ----------
190
        other
191
192
        Returns
193
        -------
194
195
        """
196
        return self.__epoch > other.__epoch
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like __epoch was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
197
198
    def __le__(self, other: Timestamp) -> bool:
199
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
200
        """
201
202
        Parameters
203
        ----------
204
        other
205
206
        Returns
207
        -------
208
209
        """
210
        return self.__epoch <= other.__epoch
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like __epoch was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
211
212
    def __lt__(self, other: Timestamp) -> bool:
213
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
214
        """
215
216
        Parameters
217
        ----------
218
        other
219
220
        Returns
221
        -------
222
223
        """
224
        return self.__epoch < other.__epoch
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like __epoch was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
225
226
    def __eq__(self, other: Timestamp) -> bool:
227
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
228
        """
229
230
        Parameters
231
        ----------
232
        other
233
234
        Returns
235
        -------
236
237
        """
238
        return self.__epoch == other.__epoch
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like __epoch was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
239
240
    def __ne__(self, other: Timestamp) -> bool:
241
        # TODO: fix docs
0 ignored issues
show
TODO and FIXME comments should generally be avoided.
Loading history...
242
        """
243
244
        Parameters
245
        ----------
246
        other
247
248
        Returns
249
        -------
250
251
        """
252
        return self.__epoch != other.__epoch
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like __epoch was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
253