1# -*- coding: utf-8 -*-
2"""Semantic time implementation."""
3
4from dfdatetime import factory
5from dfdatetime import interface
6
7
8class SemanticTime(interface.DateTimeValues):
9  """Semantic time.
10
11  Semantic time is term to describe date and time values that have specific
12  meaning such as: "Never", "Yesterday", "Not set".
13
14  Attributes:
15    is_local_time (bool): True if the date and time value is in local time.
16  """
17
18  # pylint: disable=redundant-returns-doc
19
20  _SORT_ORDER = 50
21
22  def __init__(self, string=None):
23    """Initializes a semantic time.
24
25    Args:
26      string (str): semantic representation of the time, such as:
27          "Never", "Not set".
28    """
29    super(SemanticTime, self).__init__()
30    self._string = string
31
32  @property
33  def string(self):
34    """str: semantic representation of the time, such as: "Never"."""
35    return self._string
36
37  def __eq__(self, other):
38    """Determines if the date time values are equal to other.
39
40    Args:
41      other (DateTimeValues): date time values to compare against.
42
43    Returns:
44      bool: True if the date time values are equal to other.
45    """
46    if not isinstance(other, SemanticTime):
47      return False
48
49    return self._SORT_ORDER == other._SORT_ORDER  # pylint: disable=protected-access
50
51  def __ge__(self, other):
52    """Determines if the date time values are greater than or equal to other.
53
54    Args:
55      other (DateTimeValues): date time values to compare against.
56
57    Returns:
58      bool: True if the date time values are greater than or equal to other.
59
60    Raises:
61      ValueError: if other is not an instance of DateTimeValues.
62    """
63    if not isinstance(other, interface.DateTimeValues):
64      raise ValueError('Other not an instance of DateTimeValues')
65
66    if not isinstance(other, SemanticTime):
67      return False
68
69    return self._SORT_ORDER >= other._SORT_ORDER  # pylint: disable=protected-access
70
71  def __gt__(self, other):
72    """Determines if the date time values are greater than other.
73
74    Args:
75      other (DateTimeValues): date time values to compare against.
76
77    Returns:
78      bool: True if the date time values are greater than other.
79
80    Raises:
81      ValueError: if other is not an instance of DateTimeValues.
82    """
83    if not isinstance(other, interface.DateTimeValues):
84      raise ValueError('Other not an instance of DateTimeValues')
85
86    if not isinstance(other, SemanticTime):
87      return False
88
89    return self._SORT_ORDER > other._SORT_ORDER  # pylint: disable=protected-access
90
91  def __le__(self, other):
92    """Determines if the date time values are greater than or equal to other.
93
94    Args:
95      other (DateTimeValues): date time values to compare against.
96
97    Returns:
98      bool: True if the date time values are greater than or equal to other.
99
100    Raises:
101      ValueError: if other is not an instance of DateTimeValues.
102    """
103    if not isinstance(other, interface.DateTimeValues):
104      raise ValueError('Other not an instance of DateTimeValues')
105
106    if not isinstance(other, SemanticTime):
107      return True
108
109    return self._SORT_ORDER <= other._SORT_ORDER  # pylint: disable=protected-access
110
111  def __lt__(self, other):
112    """Determines if the date time values are less than other.
113
114    Args:
115      other (DateTimeValues): date time values to compare against.
116
117    Returns:
118      bool: True if the date time values are less than other.
119
120    Raises:
121      ValueError: if other is not an instance of DateTimeValues.
122    """
123    if not isinstance(other, interface.DateTimeValues):
124      raise ValueError('Other not an instance of DateTimeValues')
125
126    if not isinstance(other, SemanticTime):
127      return True
128
129    return self._SORT_ORDER < other._SORT_ORDER  # pylint: disable=protected-access
130
131  def __ne__(self, other):
132    """Determines if the date time values are not equal to other.
133
134    Args:
135      other (DateTimeValues): date time values to compare against.
136
137    Returns:
138      bool: True if the date time values are not equal to other.
139    """
140    if not isinstance(other, SemanticTime):
141      return True
142
143    return self._SORT_ORDER != other._SORT_ORDER  # pylint: disable=protected-access
144
145  def _GetNormalizedTimestamp(self):
146    """Retrieves the normalized timestamp.
147
148    Returns:
149      decimal.Decimal: normalized timestamp, which contains the number of
150          seconds since January 1, 1970 00:00:00 and a fraction of second used
151          for increased precision, or None if the normalized timestamp cannot be
152          determined.
153    """
154    return None
155
156  def CopyFromDateTimeString(self, time_string):
157    """Copies semantic time from a date and time string.
158
159    Args:
160      time_string (str): semantic representation of the time, such as:
161          "Never", "Not set".
162
163    Raises:
164      ValueError: because semantic time cannot be copied from a string.
165    """
166    self._string = time_string
167
168  def CopyToDateTimeString(self):
169    """Copies the date time value to a date and time string.
170
171    Returns:
172      str: semantic representation of the time, such as: "Never", "Not set".
173    """
174    return self._string
175
176  def CopyToDateTimeStringISO8601(self):
177    """Copies the date time value to an ISO 8601 date and time string.
178
179    Returns:
180      str: date and time value formatted as an ISO 8601 date and time string,
181          which always be None since semantic time cannot be represented in
182          ISO 8601.
183    """
184    return None
185
186  def CopyToStatTimeTuple(self):
187    """Copies the semantic timestamp to a stat timestamp tuple.
188
189    Returns:
190      tuple[int, int]: a POSIX timestamp in seconds and the remainder in
191          100 nano seconds, which will always be None, None.
192    """
193    return None, None
194
195  def GetPlasoTimestamp(self):
196    """Retrieves a timestamp that is compatible with plaso.
197
198    Returns:
199      int: a POSIX timestamp in microseconds, which will always be 0.
200    """
201    return 0
202
203
204class InvalidTime(SemanticTime):
205  """Semantic time that represents invalid."""
206
207  _SORT_ORDER = 1
208
209  def __init__(self):
210    """Initializes a semantic time that represents invalid."""
211    super(InvalidTime, self).__init__(string='Invalid')
212
213
214class Never(SemanticTime):
215  """Semantic time that represents never."""
216
217  _SORT_ORDER = 99
218
219  def __init__(self):
220    """Initializes a semantic time that represents never."""
221    super(Never, self).__init__(string='Never')
222
223  def __eq__(self, other):
224    """Determines if the date time values are equal to other.
225
226    Args:
227      other (DateTimeValues): date time values to compare against.
228
229    Returns:
230      bool: True if the date time values are equal to other.
231    """
232    return isinstance(other, Never)
233
234  def __ge__(self, other):
235    """Determines if the date time values are greater than or equal to other.
236
237    Args:
238      other (DateTimeValues): date time values to compare against.
239
240    Returns:
241      bool: True if the date time values are greater than or equal to other.
242
243    Raises:
244      ValueError: if other is not an instance of DateTimeValues.
245    """
246    if not isinstance(other, interface.DateTimeValues):
247      raise ValueError('Other not an instance of DateTimeValues')
248
249    return True
250
251  def __gt__(self, other):
252    """Determines if the date time values are greater than other.
253
254    Args:
255      other (DateTimeValues): date time values to compare against.
256
257    Returns:
258      bool: True if the date time values are greater than other.
259
260    Raises:
261      ValueError: if other is not an instance of DateTimeValues.
262    """
263    if not isinstance(other, interface.DateTimeValues):
264      raise ValueError('Other not an instance of DateTimeValues')
265
266    return not isinstance(other, Never)
267
268  def __le__(self, other):
269    """Determines if the date time values are less than or equal to other.
270
271    Args:
272      other (DateTimeValues): date time values to compare against.
273
274    Returns:
275      bool: True if the date time values are greater than or equal to other.
276
277    Raises:
278      ValueError: if other is not an instance of DateTimeValues.
279    """
280    if not isinstance(other, interface.DateTimeValues):
281      raise ValueError('Other not an instance of DateTimeValues')
282
283    return isinstance(other, Never)
284
285  def __lt__(self, other):
286    """Determines if the date time values are less than other.
287
288    Args:
289      other (DateTimeValues): date time values to compare against.
290
291    Returns:
292      bool: True if the date time values are less than other.
293
294    Raises:
295      ValueError: if other is not an instance of DateTimeValues.
296    """
297    if not isinstance(other, interface.DateTimeValues):
298      raise ValueError('Other not an instance of DateTimeValues')
299
300    return False
301
302  def __ne__(self, other):
303    """Determines if the date time values are not equal to other.
304
305    Args:
306      other (DateTimeValues): date time values to compare against.
307
308    Returns:
309      bool: True if the date time values are not equal to other.
310    """
311    return not isinstance(other, Never)
312
313
314class NotSet(SemanticTime):
315  """Semantic time that represents not set."""
316
317  _SORT_ORDER = 2
318
319  def __init__(self):
320    """Initializes a semantic time that represents not set."""
321    super(NotSet, self).__init__(string='Not set')
322
323
324factory.Factory.RegisterDateTimeValues(SemanticTime)
325factory.Factory.RegisterDateTimeValues(InvalidTime)
326factory.Factory.RegisterDateTimeValues(Never)
327factory.Factory.RegisterDateTimeValues(NotSet)
328