Commit 677fb8ad authored by Hilko Bengen's avatar Hilko Bengen

New upstream version 20180324

parent cf36f5df
# Pylint 1.7.x configuration file
#
# This file is generated by l2tdevtools update-dependencies.py, any dependency
# related changes should be made in dependencies.ini.
[MASTER]
# A comma-separated list of package or module names from where C extensions may
......@@ -56,18 +60,45 @@ confidence=
# logging-format-interpolation
# no-self-use
# too-few-public-methods
# too-many-ancestors
# too-many-arguments
# too-many-boolean-expressions
# too-many-branches
# too-many-instance-attributes
# too-many-lines
# too-many-locals
# too-many-nested-blocks
# too-many-public-methods
# too-many-return-statements
# too-many-statements
# ungrouped-imports
# unsubscriptable-object
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,fixme,logging-format-interpolation,no-self-use,too-few-public-methods,too-many-arguments,too-many-boolean-expressions,too-many-branches,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-return-statements,too-many-statements,ungrouped-imports,unsubscriptable-object
disable=parameter-unpacking,
raw-checker-failed,
bad-inline-option,
locally-disabled,
locally-enabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
no-absolute-import,
metaclass-assignment,
eq-without-hash,
fixme,
logging-format-interpolation,
no-self-use,
too-few-public-methods,
too-many-ancestors,
too-many-boolean-expressions,
too-many-branches,
too-many-instance-attributes,
too-many-lines,
too-many-locals,
too-many-nested-blocks,
too-many-public-methods,
too-many-return-statements,
too-many-statements,
unsubscriptable-object
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
......@@ -241,11 +272,11 @@ docstring-min-length=-1
# Naming hint for function names
# function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
function-name-hint=[a-zA-Z_][a-zA-Z0-9_]*$
function-name-hint=[A-Z_][a-zA-Z0-9_]*$
# Regular expression matching correct function names
# function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
function-rgx=[a-zA-Z_][a-zA-Z0-9_]*$
function-rgx=[A-Z_][a-zA-Z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
......@@ -261,11 +292,11 @@ inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for method names
# method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
method-name-hint=[a-zA-Z_][a-zA-Z0-9_]*$
method-name-hint=(test|[A-Z_])[a-zA-Z0-9_]*$
# Regular expression matching correct method names
# method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
method-rgx=[a-zA-Z_][a-zA-Z0-9_]*$
method-rgx=(test|[A-Z_])[a-zA-Z0-9_]*$
# Naming hint for module names
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
......@@ -372,7 +403,8 @@ min-similarity-lines=4
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# max-args=5
max-args=10
# Maximum number of attributes for a class (see R0902).
max-attributes=7
......
language: python
matrix:
include:
- os: linux
- env: TARGET="pylint"
os: linux
dist: trusty
sudo: required
group: edge
python: 2.7
env: TOXENV=py27
- os: linux
- env: TARGET="linux-python27"
os: linux
dist: trusty
sudo: required
group: edge
python: 2.7
- env: TARGET="linux-python34"
os: linux
dist: trusty
sudo: required
group: edge
python: 3.4
- env: [TARGET="linux-python27-tox", TOXENV="py27"]
os: linux
dist: trusty
sudo: required
group: edge
python: 2.7
- env: [TARGET="linux-python34-tox", TOXENV="py34"]
os: linux
dist: trusty
sudo: required
group: edge
python: 3.4
env: TOXENV=py34
- os: osx
osx_image: xcode8.1
- env: [TARGET="macos-python27", PYTHONPATH="/Library/Python/2.7/site-packages/"]
os: osx
osx_image: xcode9.2
language: generic
env: PYTHONPATH=/Library/Python/2.7/site-packages/
allow_failures:
- env: TARGET="linux-python34"
install:
- ./config/travis/install.sh
- ./config/travis/install.sh
script:
- if test ${TRAVIS_OS_NAME} = "osx"; then PYTHONPATH=/Library/Python/2.7/site-packages/ /usr/bin/python ./run_tests.py; elif test ${TRAVIS_OS_NAME} = "linux"; then tox --sitepackages ${TOXENV}; fi
- python setup.py build
- python setup.py sdist
- python setup.py bdist
- if test ${TRAVIS_OS_NAME} = "linux"; then mkdir -p ${PWD}/tmp/lib/python${TRAVIS_PYTHON_VERSION}/site-packages/ && PYTHONPATH=${PWD}/tmp/lib/python${TRAVIS_PYTHON_VERSION}/site-packages/ python setup.py install --prefix=${PWD}/tmp/; fi
- ./config/travis/runtests.sh
after_success:
- if test ${TRAVIS_OS_NAME} = "linux" && test ${TRAVIS_PYTHON_VERSION} = "2.7"; then coveralls --verbose; fi
- if test ${TARGET} = "linux-python27"; then curl -o codecov.sh -s https://codecov.io/bash && /bin/bash ./codecov.sh; fi
......@@ -7,8 +7,9 @@ environment:
install:
- cmd: '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86 /release'
- cmd: "%PYTHON%\\Scripts\\pip.exe install --upgrade pip"
- cmd: "%PYTHON%\\Scripts\\pip.exe install pypiwin32 WMI"
- cmd: "%PYTHON%\\python.exe -m pip install --upgrade pip"
- cmd: "%PYTHON%\\Scripts\\pip.exe install pywin32 WMI"
- cmd: "%PYTHON%\\python.exe %PYTHON%\\Scripts\\pywin32_postinstall.py -install"
- cmd: git clone https://github.com/log2timeline/l2tdevtools.git ..\l2tdevtools
- cmd: mkdir dependencies && set PYTHONPATH=..\l2tdevtools && "%PYTHON%\\python.exe" ..\l2tdevtools\tools\update.py --download-directory dependencies --machine-type x86 --msi-targetdir "%PYTHON%" --track dev funcsigs mock pbr six
......
dfdatetime (20180110-1) unstable; urgency=low
dfdatetime (20180324-1) unstable; urgency=low
* Auto-generated
-- Log2Timeline <log2timeline-dev@googlegroups.com> Wed, 10 Jan 2018 07:04:54 +0100
\ No newline at end of file
-- Log2Timeline <log2timeline-dev@googlegroups.com> Sat, 24 Mar 2018 14:06:11 +0100
\ No newline at end of file
......@@ -2,7 +2,7 @@ Source: dfdatetime
Section: python
Priority: extra
Maintainer: Log2Timeline maintainers <log2timeline-maintainers@googlegroups.com>
Build-Depends: debhelper (>= 7), python-all (>= 2.7~), python-setuptools, python3-all (>= 3.4~), python3-setuptools
Build-Depends: debhelper (>= 9), python-all (>= 2.7~), python-setuptools, python3-all (>= 3.4~), python3-setuptools
Standards-Version: 3.9.5
X-Python-Version: >= 2.7
X-Python3-Version: >= 3.4
......
#!/bin/bash
#
# Script to set up Travis-CI test VM.
COVERALL_DEPENDENCIES="python-coverage python-coveralls python-docopt";
#
# This file is generated by l2tdevtools update-dependencies.py any dependency
# related changes should be made in dependencies.ini.
L2TBINARIES_DEPENDENCIES="";
......@@ -10,19 +11,36 @@ L2TBINARIES_TEST_DEPENDENCIES="funcsigs mock pbr six";
PYTHON2_DEPENDENCIES="";
PYTHON2_TEST_DEPENDENCIES="python-mock python-tox";
PYTHON2_TEST_DEPENDENCIES="python-coverage python-mock python-tox";
PYTHON3_DEPENDENCIES="";
PYTHON3_TEST_DEPENDENCIES="python3-mock python3-setuptools python3-tox";
# Exit on error.
set -e;
if test ${TRAVIS_OS_NAME} = "osx";
then
git clone https://github.com/log2timeline/l2tdevtools.git;
mv l2tdevtools ../;
mkdir dependencies;
PYTHONPATH=../l2tdevtools ../l2tdevtools/tools/update.py --download-directory dependencies --track dev ${L2TBINARIES_DEPENDENCIES} ${L2TBINARIES_TEST_DEPENDENCIES};
git clone https://github.com/log2timeline/l2tbinaries.git -b dev;
mv l2tbinaries ../;
for PACKAGE in ${L2TBINARIES_DEPENDENCIES};
do
echo "Installing: ${PACKAGE}";
sudo /usr/bin/hdiutil attach ../l2tbinaries/macos/${PACKAGE}-*.dmg;
sudo /usr/sbin/installer -target / -pkg /Volumes/${PACKAGE}-*.pkg/${PACKAGE}-*.pkg;
sudo /usr/bin/hdiutil detach /Volumes/${PACKAGE}-*.pkg
done
for PACKAGE in ${L2TBINARIES_TEST_DEPENDENCIES};
do
echo "Installing: ${PACKAGE}";
sudo /usr/bin/hdiutil attach ../l2tbinaries/macos/${PACKAGE}-*.dmg;
sudo /usr/sbin/installer -target / -pkg /Volumes/${PACKAGE}-*.pkg/${PACKAGE}-*.pkg;
sudo /usr/bin/hdiutil detach /Volumes/${PACKAGE}-*.pkg
done
elif test ${TRAVIS_OS_NAME} = "linux";
then
......@@ -30,7 +48,15 @@ then
sudo add-apt-repository ppa:gift/dev -y;
sudo apt-get update -q;
# Only install the Python 2 dependencies.
# Also see: https://docs.travis-ci.com/user/languages/python/#Travis-CI-Uses-Isolated-virtualenvs
sudo apt-get install -y ${COVERALL_DEPENDENCIES} ${PYTHON2_DEPENDENCIES} ${PYTHON2_TEST_DEPENDENCIES};
if test ${TRAVIS_PYTHON_VERSION} = "2.7";
then
sudo apt-get install -y ${PYTHON2_DEPENDENCIES} ${PYTHON2_TEST_DEPENDENCIES};
else
sudo apt-get install -y ${PYTHON3_DEPENDENCIES} ${PYTHON3_TEST_DEPENDENCIES};
fi
if test ${TARGET} = "pylint";
then
sudo apt-get install -y pylint;
fi
fi
#!/bin/bash
#
# Script to run tests on Travis-CI.
#
# This file is generated by l2tdevtools update-dependencies.py, any dependency
# related changes should be made in dependencies.ini.
# Exit on error.
set -e;
if test "${TARGET}" = "pylint";
then
pylint --version
for FILE in `find setup.py dfdatetime tests -name \*.py`;
do
echo "Checking: ${FILE}";
pylint --rcfile=.pylintrc ${FILE};
done
elif test "${TRAVIS_OS_NAME}" = "osx";
then
PYTHONPATH=/Library/Python/2.7/site-packages/ /usr/bin/python ./run_tests.py;
python ./setup.py build
python ./setup.py sdist
python ./setup.py bdist
elif test "${TRAVIS_OS_NAME}" = "linux";
then
if test -n "${TOXENV}";
then
tox --sitepackages ${TOXENV};
elif test "${TRAVIS_PYTHON_VERSION}" = "2.7";
then
coverage erase
coverage run --source=dfdatetime --omit="*_test*,*__init__*,*test_lib*" ./run_tests.py
else
python ./run_tests.py
fi
python ./setup.py build
python ./setup.py sdist
python ./setup.py bdist
TMPDIR="${PWD}/tmp";
TMPSITEPACKAGES="${TMPDIR}/lib/python${TRAVIS_PYTHON_VERSION}/site-packages";
mkdir -p ${TMPSITEPACKAGES};
PYTHONPATH=${TMPSITEPACKAGES} python ./setup.py install --prefix=${TMPDIR};
fi
......@@ -5,4 +5,4 @@ dfDateTime, or Digital Forensics date and time, provides date and time
objects to preserve accuracy and precision.
"""
__version__ = '20180110'
__version__ = '20180324'
......@@ -3,10 +3,20 @@
from __future__ import unicode_literals
import decimal
from dfdatetime import definitions
from dfdatetime import interface
class CocoaTimeEpoch(interface.DateTimeEpoch):
"""Cocoa time epoch."""
def __init__(self):
"""Initializes a Cocoa time epoch."""
super(CocoaTimeEpoch, self).__init__(2001, 1, 1)
class CocoaTime(interface.DateTimeValues):
"""Cocoa timestamp.
......@@ -20,13 +30,12 @@ class CocoaTime(interface.DateTimeValues):
Attributes:
is_local_time (bool): True if the date and time value is in local time.
precision (str): precision of the date and time value, which should
be one of the PRECISION_VALUES in definitions.
timestamp (float): Cocoa timestamp.
"""
# The difference between Jan 1, 2001 and Jan 1, 1970 in seconds.
# The difference between January 1, 2001 and January 1, 1970 in seconds.
_COCOA_TO_POSIX_BASE = -978307200
_EPOCH = CocoaTimeEpoch()
def __init__(self, timestamp=None):
"""Initializes a Cocoa timestamp.
......@@ -34,8 +43,28 @@ class CocoaTime(interface.DateTimeValues):
timestamp (Optional[float]): Cocoa timestamp.
"""
super(CocoaTime, self).__init__()
self.precision = definitions.PRECISION_1_SECOND
self.timestamp = timestamp
self._precision = definitions.PRECISION_1_SECOND
self._timestamp = timestamp
@property
def timestamp(self):
"""float: Cocoa timestamp or None if timestamp is not set."""
return self._timestamp
def _GetNormalizedTimestamp(self):
"""Retrieves the normalized timestamp.
Returns:
float: normalized timestamp, which contains the number of seconds since
January 1, 1970 00:00:00 and a fraction of second used for increased
precision, or None if the normalized timestamp cannot be determined.
"""
if self._normalized_timestamp is None:
if self._timestamp is not None:
self._normalized_timestamp = (
decimal.Decimal(self._timestamp) - self._COCOA_TO_POSIX_BASE)
return self._normalized_timestamp
def CopyFromDateTimeString(self, time_string):
"""Copies a Cocoa timestamp from a date and time string.
......@@ -70,23 +99,10 @@ class CocoaTime(interface.DateTimeValues):
if microseconds is not None:
timestamp += float(microseconds) / definitions.MICROSECONDS_PER_SECOND
self.timestamp = timestamp
self._normalized_timestamp = None
self._timestamp = timestamp
self.is_local_time = False
def CopyToStatTimeTuple(self):
"""Copies the Cocoa timestamp to a stat timestamp tuple.
Returns:
tuple[int, int]: a POSIX timestamp in seconds and the remainder in
100 nano seconds or (None, None) on error.
"""
if self.timestamp is None:
return None, None
timestamp = self.timestamp - self._COCOA_TO_POSIX_BASE
remainder = int((timestamp % 1) * self._100NS_PER_SECOND)
return int(timestamp), remainder
def CopyToDateTimeString(self):
"""Copies the Cocoa timestamp to a date and time string.
......@@ -94,30 +110,34 @@ class CocoaTime(interface.DateTimeValues):
str: date and time value formatted as:
YYYY-MM-DD hh:mm:ss.######
"""
if self.timestamp is None:
if self._timestamp is None:
return
number_of_days, hours, minutes, seconds = self._GetTimeValues(
int(self.timestamp))
int(self._timestamp))
year, month, day_of_month = self._GetDateValues(
number_of_days, 2001, 1, 1)
year, month, day_of_month = self._GetDateValuesWithEpoch(
number_of_days, self._EPOCH)
microseconds = int(
(self.timestamp % 1) * definitions.MICROSECONDS_PER_SECOND)
(self._timestamp % 1) * definitions.MICROSECONDS_PER_SECOND)
return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:06d}'.format(
year, month, day_of_month, hours, minutes, seconds, microseconds)
def GetPlasoTimestamp(self):
"""Retrieves a timestamp that is compatible with plaso.
def GetDate(self):
"""Retrieves the date represented by the date and time values.
Returns:
int: a POSIX timestamp in microseconds or None on error.
tuple[int, int, int]: year, month, day of month or (None, None, None)
if the date and time values do not represent a date.
"""
if self.timestamp is None:
return
return None, None, None
try:
number_of_days, _, _, _ = self._GetTimeValues(int(self.timestamp))
return self._GetDateValuesWithEpoch(number_of_days, self._EPOCH)
timestamp = definitions.MICROSECONDS_PER_SECOND * (
self.timestamp - self._COCOA_TO_POSIX_BASE)
return int(timestamp)
except ValueError:
return None, None, None
......@@ -6,15 +6,14 @@ from __future__ import unicode_literals
import warnings
def deprecated(function):
def deprecated(function): # pylint: disable=invalid-name
"""Decorator to mark functions or methods as deprecated."""
def IssueDeprecationWarning(*args, **kwargs):
"""Issue a deprecation warning."""
warnings.simplefilter('always', DeprecationWarning)
warnings.simplefilter('default', DeprecationWarning)
warnings.warn('Call to deprecated function: {0:s}.'.format(
function.__name__), category=DeprecationWarning, stacklevel=2)
warnings.simplefilter('default', DeprecationWarning)
return function(*args, **kwargs)
......
......@@ -16,6 +16,7 @@ DECISECONDS_PER_SECOND = 10
MILLISECONDS_PER_SECOND = 1000
MICROSECONDS_PER_DAY = 86400000000
MICROSECONDS_PER_SECOND = 1000000
MICROSECONDS_PER_DECISECOND = 100000
MICROSECONDS_PER_MILLISECOND = 1000
......
......@@ -3,10 +3,20 @@
from __future__ import unicode_literals
import decimal
from dfdatetime import definitions
from dfdatetime import interface
class DelphiDateTimeEpoch(interface.DateTimeEpoch):
"""Delphi TDateTime epoch."""
def __init__(self):
"""Initializes a Delphi TDateTime epoch."""
super(DelphiDateTimeEpoch, self).__init__(1899, 12, 30)
class DelphiDateTime(interface.DateTimeValues):
"""Delphi TDateTime timestamp.
......@@ -22,15 +32,11 @@ class DelphiDateTime(interface.DateTimeValues):
Attributes:
is_local_time (bool): True if the date and time value is in local time.
precision (str): precision of the date and time value, which should
be one of the PRECISION_VALUES in definitions.
timestamp (float): Delphi TDateTime timestamp.
"""
# The difference between Dec 30, 1899 and Jan 1, 1970 in days.
# The difference between December 30, 1899 and January 1, 1970 in days.
_DELPHI_TO_POSIX_BASE = 25569
# The number of microseconds per day.
_MICROSECONDS_PER_DAY = 86400000000
_EPOCH = DelphiDateTimeEpoch()
def __init__(self, timestamp=None):
"""Initializes a Delphi TDateTime timestamp.
......@@ -39,8 +45,30 @@ class DelphiDateTime(interface.DateTimeValues):
timestamp (Optional[float]): Delphi TDateTime timestamp.
"""
super(DelphiDateTime, self).__init__()
self.precision = definitions.PRECISION_1_MILLISECOND
self.timestamp = timestamp
self._precision = definitions.PRECISION_1_MILLISECOND
self._timestamp = timestamp
@property
def timestamp(self):
"""float: Delphi TDateTime timestamp or None if timestamp is not set."""
return self._timestamp
def _GetNormalizedTimestamp(self):
"""Retrieves the normalized timestamp.
Returns:
decimal.Decimal: normalized timestamp, which contains the number of
seconds since January 1, 1970 00:00:00 and a fraction of second used
for increased precision, or None if the normalized timestamp cannot be
determined.
"""
if self._normalized_timestamp is None:
if self._timestamp is not None:
self._normalized_timestamp = (
decimal.Decimal(self._timestamp) - self._DELPHI_TO_POSIX_BASE)
self._normalized_timestamp *= definitions.SECONDS_PER_DAY
return self._normalized_timestamp
def CopyFromDateTimeString(self, time_string):
"""Copies a Delphi TDateTime timestamp from a string.
......@@ -76,26 +104,12 @@ class DelphiDateTime(interface.DateTimeValues):
timestamp = float(timestamp) / definitions.SECONDS_PER_DAY
timestamp += self._DELPHI_TO_POSIX_BASE
if microseconds is not None:
timestamp += float(microseconds) / self._MICROSECONDS_PER_DAY
timestamp += float(microseconds) / definitions.MICROSECONDS_PER_DAY
self.timestamp = timestamp
self._normalized_timestamp = None
self._timestamp = timestamp
self.is_local_time = False
def CopyToStatTimeTuple(self):
"""Copies the Delphi TDateTime timestamp to a stat timestamp tuple.
Returns:
tuple[int, int]: a POSIX timestamp in seconds and the remainder in
100 nano seconds or (None, None) on error.
"""
if self.timestamp is None:
return None, None
timestamp = definitions.SECONDS_PER_DAY * (
self.timestamp - self._DELPHI_TO_POSIX_BASE)
remainder = int((timestamp % 1) * self._100NS_PER_SECOND)
return int(timestamp), remainder
def CopyToDateTimeString(self):
"""Copies the Delphi TDateTime timestamp to a date and time string.
......@@ -103,16 +117,16 @@ class DelphiDateTime(interface.DateTimeValues):
str: date and time value formatted as:
YYYY-MM-DD hh:mm:ss.######
"""
if self.timestamp is None:
if self._timestamp is None:
return
number_of_seconds = self.timestamp * definitions.SECONDS_PER_DAY
number_of_seconds = self._timestamp * definitions.SECONDS_PER_DAY
number_of_days, hours, minutes, seconds = self._GetTimeValues(
int(number_of_seconds))
year, month, day_of_month = self._GetDateValues(
number_of_days, 1899, 12, 30)
year, month, day_of_month = self._GetDateValuesWithEpoch(
number_of_days, self._EPOCH)
microseconds = int(
(number_of_seconds % 1) * definitions.MICROSECONDS_PER_SECOND)
......@@ -120,16 +134,20 @@ class DelphiDateTime(interface.DateTimeValues):
return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:06d}'.format(
year, month, day_of_month, hours, minutes, seconds, microseconds)
def GetPlasoTimestamp(self):
"""Retrieves a timestamp that is compatible with plaso.
def GetDate(self):
"""Retrieves the date represented by the date and time values.
Returns:
int: a POSIX timestamp in microseconds or None on error.
tuple[int, int, int]: year, month, day of month or (None, None, None)
if the date and time values do not represent a date.
"""
if self.timestamp is None:
return
return None, None, None
try:
number_of_seconds = self.timestamp * definitions.SECONDS_PER_DAY
number_of_days, _, _, _ = self._GetTimeValues(int(number_of_seconds))
return self._GetDateValuesWithEpoch(number_of_days, self._EPOCH)
timestamp = (
(self.timestamp - self._DELPHI_TO_POSIX_BASE) *
self._MICROSECONDS_PER_DAY)
return int(timestamp)
except ValueError:
return None, None, None
......@@ -3,10 +3,12 @@
from __future__ import unicode_literals
import decimal
import time
from dfdatetime import definitions
from dfdatetime import interface
from dfdatetime import posix_time
class FakeTime(interface.DateTimeValues):
......@@ -17,19 +19,38 @@ class FakeTime(interface.DateTimeValues):
Attributes:
is_local_time (bool): True if the date and time value is in local time.
precision (str): precision of the date and time value, which should
be one of the PRECISION_VALUES in definitions.
"""
_EPOCH = posix_time.PosixTimeEpoch()
def __init__(self):
"""Initializes a fake timestamp."""
super(FakeTime, self).__init__()
# Note that time.time() and divmod return floating point values.
timestamp, fraction_of_second = divmod(time.time(), 1)
super(FakeTime, self).__init__()
self._microseconds = int(
fraction_of_second * definitions.MICROSECONDS_PER_SECOND)
self._number_of_seconds = int(timestamp)
self.precision = definitions.PRECISION_1_MICROSECOND
self._precision = definitions.PRECISION_1_MICROSECOND
def _GetNormalizedTimestamp(self):
"""Retrieves the normalized timestamp.
Returns:
decimal.Decimal: normalized timestamp, which contains the number of
seconds since January 1, 1970 00:00:00 and a fraction of second used
for increased precision, or None if the normalized timestamp cannot be
determined.
"""
if self._normalized_timestamp is None:
if self._number_of_seconds is not None:
self._normalized_timestamp = (
decimal.Decimal(self._microseconds) /
definitions.MICROSECONDS_PER_SECOND)
self._normalized_timestamp += decimal.Decimal(self._number_of_seconds)
return self._normalized_timestamp
def CopyFromDateTimeString(self, time_string):
"""Copies a fake timestamp from a date and time string.
......@@ -52,28 +73,13 @@ class FakeTime(interface.DateTimeValues):
minutes = date_time_values.get('minutes', 0)
seconds = date_time_values.get('seconds', 0)
self._normalized_timestamp = None
self._number_of_seconds = self._GetNumberOfSecondsFromElements(
year, month, day_of_month, hours, minutes, seconds)
self._microseconds = date_time_values.get('microseconds', None)
self.is_local_time = False
def CopyToStatTimeTuple(self):
"""Copies the fake timestamp to a stat timestamp tuple.
Returns:
tuple[int, int]: a POSIX timestamp in seconds and the remainder in
100 nano seconds or (None, None) on error.
"""
if self._number_of_seconds is None:
return None, None
if self._microseconds is not None:
return self._number_of_seconds, (
self._microseconds * self._100NS_PER_MICROSECOND)
return self._number_of_seconds, None
def CopyToDateTimeString(self):
"""Copies the fake timestamp to a date and time string.
......@@ -88,8 +94,8 @@ class FakeTime(interface.DateTimeValues):
number_of_days, hours, minutes, seconds = self._GetTimeValues(
self._number_of_seconds)
year, month, day_of_month = self._GetDateValues(
number_of_days, 1970, 1, 1)
year, month, day_of_month = self._GetDateValuesWithEpoch(
number_of_days, self._EPOCH)
if self._microseconds is None:
return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(
......@@ -99,17 +105,19 @@ class FakeTime(interface.DateTimeValues):
year, month, day_of_month, hours, minutes, seconds,