Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added nanosecond time elements #284

Merged
merged 1 commit into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions config/dpkg/changelog
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
dfdatetime (20240330-1) unstable; urgency=low
dfdatetime (20240504-1) unstable; urgency=low

* Auto-generated

-- Log2Timeline maintainers <log2timeline-maintainers@googlegroups.com> Sat, 30 Mar 2024 05:58:15 +0100
-- Log2Timeline maintainers <log2timeline-maintainers@googlegroups.com> Sat, 04 May 2024 07:02:38 +0200
2 changes: 1 addition & 1 deletion dfdatetime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@
from dfdatetime import webkit_time


__version__ = '20240330'
__version__ = '20240504'
148 changes: 148 additions & 0 deletions dfdatetime/time_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,154 @@ def NewFromDeltaAndYear(self, year):
return self.NewFromDeltaAndDate(year, 0, 0)


class TimeElementsInNanoseconds(TimeElementsWithFractionOfSecond):
"""Time elements in nanoseconds.

Attributes:
fraction_of_second (decimal.Decimal): fraction of second, which must be a
value between 0.0 and 1.0.
is_local_time (bool): True if the date and time value is in local time.
precision (str): precision of the date of the date and time value, that
represents 1 nanosecond (PRECISION_1_NANOSECOND).
"""

def __init__(
self, is_delta=False, precision=None, time_elements_tuple=None,
time_zone_offset=None):
"""Initializes time elements.

Args:
is_delta (Optional[bool]): True if the date and time value is relative to
another date and time value.
precision (Optional[str]): precision of the date and time value, which
should be one of the PRECISION_VALUES in definitions.
time_elements_tuple (Optional[tuple[int, int, int, int, int, int, int]]):
time elements, contains year, month, day of month, hours, minutes,
seconds and nanoseconds.
time_zone_offset (Optional[int]): time zone offset in number of minutes
from UTC or None if not set.

Raises:
ValueError: if the time elements tuple is invalid.
"""
fraction_of_second = None
if time_elements_tuple:
number_of_elements = len(time_elements_tuple)
if number_of_elements < 7:
raise ValueError((
f'Invalid time elements tuple at least 7 elements required,'
f'got: {number_of_elements:d}'))

nanoseconds = time_elements_tuple[6]
time_elements_tuple = time_elements_tuple[:6]

if (nanoseconds < 0 or
nanoseconds >= definitions.NANOSECONDS_PER_SECOND):
raise ValueError('Invalid number of nanoseconds.')

fraction_of_second = (
decimal.Decimal(nanoseconds) / definitions.NANOSECONDS_PER_SECOND)

super(TimeElementsInNanoseconds, self).__init__(
fraction_of_second=fraction_of_second, is_delta=is_delta,
precision=precision or definitions.PRECISION_1_NANOSECOND,
time_elements_tuple=time_elements_tuple,
time_zone_offset=time_zone_offset)

@property
def nanoseconds(self):
"""int: number of nanoseconds."""
return int(self.fraction_of_second * definitions.NANOSECONDS_PER_SECOND)

def CopyFromStringTuple(self, time_elements_tuple):
"""Copies time elements from string-based time elements tuple.

Args:
time_elements_tuple (Optional[tuple[str, str, str, str, str, str, str]]):
time elements, contains year, month, day of month, hours, minutes,
seconds and nanoseconds.

Raises:
ValueError: if the time elements tuple is invalid.
"""
number_of_elements = len(time_elements_tuple)
if len(time_elements_tuple) < 7:
raise ValueError((
f'Invalid time elements tuple at least 7 elements required,'
f'got: {number_of_elements:d}'))

year, month, day_of_month, hours, minutes, seconds, nanoseconds = (
time_elements_tuple)

try:
nanoseconds = int(nanoseconds, 10)
except (TypeError, ValueError):
raise ValueError(f'Invalid nanosecond value: {nanoseconds!s}')

if nanoseconds < 0 or nanoseconds >= definitions.NANOSECONDS_PER_SECOND:
raise ValueError('Invalid number of nanoseconds.')

fraction_of_second = (
decimal.Decimal(nanoseconds) / definitions.NANOSECONDS_PER_SECOND)

time_elements_tuple = (
year, month, day_of_month, hours, minutes, seconds,
str(fraction_of_second))

super(TimeElementsInNanoseconds, self).CopyFromStringTuple(
time_elements_tuple)

def NewFromDeltaAndDate(self, year, month, day_of_month):
"""Creates a new time elements instance from a date time delta and a year.

Args:
year (int): year.
month (int): month, where 1 represents January and 0 if not set.
day_of_month (int): day of month, where 1 represents the first day and 0
if not set.

Returns:
TimeElementsInNanoseconds: time elements or None if time elements are
missing.

Raises:
ValueError: if the instance is not a date time delta.
"""
if not self._is_delta:
raise ValueError('Not a date time delta.')

if self._time_elements_tuple is None:
return None

delta_year, delta_month, delta_day_of_month, hours, minutes, seconds = (
self._time_elements_tuple)

time_elements_tuple = (
year + delta_year, month + delta_month,
day_of_month + delta_day_of_month, hours, minutes, seconds,
self.nanoseconds)

return TimeElementsInNanoseconds(
precision=self._precision, time_elements_tuple=time_elements_tuple,
time_zone_offset=self._time_zone_offset)

def NewFromDeltaAndYear(self, year):
"""Creates a new time elements instance from a date time delta and a year.

Args:
year (int): year.

Returns:
TimeElementsInNanoseconds: time elements or None if time elements are
missing.

Raises:
ValueError: if the instance is not a date time delta.
"""
return self.NewFromDeltaAndDate(year, 0, 0)


factory.Factory.RegisterDateTimeValues(TimeElements)
factory.Factory.RegisterDateTimeValues(TimeElementsInMilliseconds)
factory.Factory.RegisterDateTimeValues(TimeElementsInMicroseconds)
factory.Factory.RegisterDateTimeValues(TimeElementsInNanoseconds)
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = dfdatetime
version = 20240330
version = 20240504
description = Digital Forensics date and time (dfDateTime).
long_description = dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision.
long_description_content_type = text/plain
Expand Down
Loading