pax_global_header00006660000000000000000000000064132253264060014515gustar00rootroot0000000000000052 comment=fae39c7b5e721facbafbb9959ed5eb5661f80f50 dfdatetime-20180110/000077500000000000000000000000001322532640600140615ustar00rootroot00000000000000dfdatetime-20180110/.gitignore000066400000000000000000000004241322532640600160510ustar00rootroot00000000000000# Files to ignore by git. # Back-up files *~ *.swp # Generic auto-generated build files *.pyc *.pyo # Specific auto-generated build files /.tox /__pycache__ /build /dfdatetime.egg-info /dist # Code review files /.review # Test coverage files .coverage tests-coverage.txt dfdatetime-20180110/.pylintrc000066400000000000000000000373541322532640600157420ustar00rootroot00000000000000[MASTER] # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code extension-pkg-whitelist= # Add files or directories to the blacklist. They should be base names, not # paths. ignore=CVS # Add files or directories matching the regex patterns to the blacklist. The # regex matches against base names, not paths. ignore-patterns= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Use multiple processes to speed up Pylint. jobs=1 # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= # Pickle collected data for later comparisons. persistent=yes # Specify a configuration file. #rcfile= # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED confidence= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once).You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" # # Additional: # 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=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 # 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 # multiple time (only on the command line, not in the configuration file where # it should appear only once). See also the "--disable" option for examples. enable= [REPORTS] # Python expression which should return a note less than 10 (10 is the highest # note). You have access to the variables errors warning, statement which # respectively contain the number of errors / warnings messages and the total # number of statements analyzed. This is used by the global evaluation report # (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details #msg-template= # Set the output format. Available formats are text, parseable, colorized, json # and msvs (visual studio).You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=text # Tells whether to display a full report or only the messages reports=no # Activate the evaluation score. # score=yes score=no [REFACTORING] # Maximum number of nested blocks for function / method body max-nested-blocks=5 [VARIABLES] # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= # Tells whether unused global variables should be treated as a violation. allow-global-unused-variables=yes # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_,_cb # A regular expression matching the name of dummy variables (i.e. expectedly # not used). dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ # Argument names that match this expression will be ignored. Default to name # with leading underscore ignored-argument-names=_.*|^ignored_|^unused_ # Tells whether we should check for unused import in __init__ files. init-import=no # List of qualified module names which can have objects that can redefine # builtins. redefining-builtins-modules=six.moves,future.builtins [TYPECHECK] # List of decorators that produce context managers, such as # contextlib.contextmanager. Add to this list to register other decorators that # produce valid context managers. contextmanager-decorators=contextlib.contextmanager # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # This flag controls whether pylint should warn about no-member and similar # checks whenever an opaque object is returned when inferring. The inference # can return multiple potential results while evaluating a Python object, but # some branches might not be evaluated, which results in partial inference. In # that case, it might be useful to still emit no-member and other checks for # the rest of the inferred objects. ignore-on-opaque-inference=yes # List of class names for which member attributes should not be checked (useful # for classes with dynamically set attributes). This supports the use of # qualified names. ignored-classes=optparse.Values,thread._local,_thread._local # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # Show a hint with possible names when a member name was not found. The aspect # of finding the hint is based on edit distance. missing-member-hint=yes # The minimum edit distance a name should have in order to be considered a # similar match for a missing member name. missing-member-hint-distance=1 # The total number of similar names that should be taken in consideration when # showing a hint for a missing member. missing-member-max-choices=1 [LOGGING] # Logging modules to check that the string format arguments are in logging # function parameter format logging-modules=logging [BASIC] # Naming hint for argument names # argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ argument-name-hint=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Regular expression matching correct argument names # argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ argument-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Naming hint for attribute names # attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ attr-name-hint=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Regular expression matching correct attribute names # attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ attr-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata # Naming hint for class attribute names # class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]*|(__.*__))$ # Regular expression matching correct class attribute names # class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]*|(__.*__))$ # Naming hint for class names class-name-hint=[A-Z_][a-zA-Z0-9]+$ # Regular expression matching correct class names class-rgx=[A-Z_][a-zA-Z0-9]+$ # Naming hint for constant names # const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ const-name-hint=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$ # Regular expression matching correct constant names # const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. 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_]*$ # 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_]*$ # Good variable names which should always be accepted, separated by a comma good-names=i,j,k,ex,Run,_ # Include a hint for the correct naming format with invalid-name include-naming-hint=no # Naming hint for inline iteration names inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ # Regular expression matching correct inline iteration names 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_]*$ # 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_]*$ # Naming hint for module names module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Regular expression matching correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=^_ # List of decorators that produce properties, such as abc.abstractproperty. Add # to this list to register other decorators that produce valid properties. property-classes=abc.abstractproperty # Naming hint for variable names # variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ variable-name-hint=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ # Regular expression matching correct variable names # variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ variable-rgx=(([a-z][a-z0-9_]*)|(_[a-z0-9_]*))$ [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=FIXME,XXX,TODO [FORMAT] # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). # indent-string=' ' indent-string=' ' # Maximum number of characters on a single line. # max-line-length=100 max-line-length=80 # Maximum number of lines in a module max-module-lines=1000 # List of optional constructs for which whitespace checking is disabled. `dict- # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. # `trailing-comma` allows a space between comma and closing bracket: (a, ). # `empty-line` allows space-only lines. no-space-check=trailing-comma,dict-separator # Allow the body of a class to be on the same line as the declaration if body # contains single statement. single-line-class-stmt=no # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no [SPELLING] # Spelling dictionary name. Available dictionaries: en_US (myspell). spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to indicated private dictionary in # --spelling-private-dict-file option instead of raising a message. spelling-store-unknown-words=no [SIMILARITIES] # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no # Minimum lines number of a similarity. min-similarity-lines=4 [DESIGN] # Maximum number of arguments for function / method max-args=5 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Maximum number of boolean expressions in a if statement max-bool-expr=5 # Maximum number of branch for function / method body max-branches=12 # Maximum number of locals for function / method body max-locals=15 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of public methods for a class (see R0904). max-public-methods=20 # Maximum number of return / yield for function / method body max-returns=6 # Maximum number of statements in function / method body max-statements=50 # Minimum number of public methods for a class (see R0903). min-public-methods=2 [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__,__new__,setUp # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict,_fields,_replace,_source,_make # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs [IMPORTS] # Allow wildcard imports from modules that define __all__. allow-wildcard-with-all=no # Analyse import fallback blocks. This can be used to support both Python 2 and # 3 compatible code, which means that the block might have code that exists # only in one or another interpreter, leading to false positives when analysed. analyse-fallback-blocks=no # Deprecated modules which should not be used, separated by a comma deprecated-modules=optparse,tkinter.tix # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled) ext-import-graph= # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= # Force import order to recognize a module as part of the standard # compatibility libraries. known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "Exception" overgeneral-exceptions=Exception dfdatetime-20180110/.style.yapf000066400000000000000000000001361322532640600161600ustar00rootroot00000000000000[style] based_on_style = chromium COALESCE_BRACKETS = True SPLIT_BEFORE_FIRST_ARGUMENT = True dfdatetime-20180110/.travis.yml000066400000000000000000000020261322532640600161720ustar00rootroot00000000000000language: python matrix: include: - os: linux dist: trusty sudo: required group: edge python: 2.7 env: TOXENV=py27 - os: linux dist: trusty sudo: required group: edge python: 3.4 env: TOXENV=py34 - os: osx osx_image: xcode8.1 language: generic env: PYTHONPATH=/Library/Python/2.7/site-packages/ install: - ./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 after_success: - if test ${TRAVIS_OS_NAME} = "linux" && test ${TRAVIS_PYTHON_VERSION} = "2.7"; then coveralls --verbose; fi dfdatetime-20180110/ACKNOWLEDGEMENTS000066400000000000000000000012251322532640600163360ustar00rootroot00000000000000Acknowledgements: dfdatetime Copyright 2016 The dfDateTime Project Authors. Please see the AUTHORS file for details on individual authors. dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision. dfDateTime, originates from the dfVFS project [https://github.com/log2timeline/dfvfs] and the dfWinReg project [//github.com/log2timeline/dfvfs]. It was largely rewritten and made into a stand-alone project to provide more flexibility and allow other projects to make use of the Digital Forensics date and time objects. dfDateTime is currently developed and maintained by: * Daniel White * Joachim Metz dfdatetime-20180110/AUTHORS000066400000000000000000000005601322532640600151320ustar00rootroot00000000000000# Names should be added to this file with this pattern: # # For individuals: # Name (email address) # # For organizations: # Organization (fnmatch pattern) # # See python fnmatch module documentation for more information. Google Inc. (*@google.com) Kristinn Gudjonsson (kiddi@kiddaland.net) Joachim Metz (joachim.metz@gmail.com) Daniel White (onager@deerpie.com) dfdatetime-20180110/LICENSE000066400000000000000000000261361322532640600150760ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. dfdatetime-20180110/MANIFEST.in000066400000000000000000000007021322532640600156160ustar00rootroot00000000000000include ACKNOWLEDGEMENTS AUTHORS LICENSE README include dependencies.ini run_tests.py utils/__init__.py utils/dependencies.py include utils/check_dependencies.py exclude .gitignore exclude *.pyc recursive-include config * recursive-exclude dfdatetime *.pyc # The test scripts are not required in a binary distribution package they # are considered source distribution files and excluded in find_package() # in setup.py. recursive-include tests *.py dfdatetime-20180110/README000066400000000000000000000004631322532640600147440ustar00rootroot00000000000000dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision. For more information see: * Project documentation: https://github.com/log2timeline/dfdatetime/wiki/Home * How to build from source: https://github.com/log2timeline/dfdatetime/wiki/Building dfdatetime-20180110/appveyor.yml000066400000000000000000000013001322532640600164430ustar00rootroot00000000000000environment: matrix: - TARGET: python27 PYTHON: "C:\\Python27" - TARGET: python36 PYTHON: "C:\\Python36" 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: 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 build: off test_script: - "%PYTHON%\\python.exe run_tests.py" dfdatetime-20180110/config/000077500000000000000000000000001322532640600153265ustar00rootroot00000000000000dfdatetime-20180110/config/dpkg/000077500000000000000000000000001322532640600162535ustar00rootroot00000000000000dfdatetime-20180110/config/dpkg/changelog000066400000000000000000000002301322532640600201200ustar00rootroot00000000000000dfdatetime (20180110-1) unstable; urgency=low * Auto-generated -- Log2Timeline Wed, 10 Jan 2018 07:04:54 +0100dfdatetime-20180110/config/dpkg/clean000066400000000000000000000000271322532640600172570ustar00rootroot00000000000000dfdatetime/*.pyc *.pyc dfdatetime-20180110/config/dpkg/compat000066400000000000000000000000021322532640600174510ustar00rootroot000000000000009 dfdatetime-20180110/config/dpkg/control000066400000000000000000000015571322532640600176660ustar00rootroot00000000000000Source: dfdatetime Section: python Priority: extra Maintainer: Log2Timeline maintainers Build-Depends: debhelper (>= 7), 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 Homepage: https://github.com/log2timeline/dfdatetime Package: python-dfdatetime Architecture: all Depends: ${python:Depends}, ${misc:Depends} Description: Python 2 module of dfDateTime dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision. Package: python3-dfdatetime Architecture: all Depends: ${python3:Depends}, ${misc:Depends} Description: Python 3 module of dfDateTime dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision. dfdatetime-20180110/config/dpkg/copyright000066400000000000000000000017101322532640600202050ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: dfdatetime Source: https://github.com/log2timeline/dfdatetime/ Files: * Copyright: 2016 The dfDateTime project authors. License: Apache-2.0 Files: debian/* Copyright: 2016 The dfDateTime project authors. License: Apache-2.0 License: Apache-2.0 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at . http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. . On Debian systems, the complete text of the Apache version 2.0 license can be found in "/usr/share/common-licenses/Apache-2.0". dfdatetime-20180110/config/dpkg/python-dfdatetime.install000066400000000000000000000001451322532640600232700ustar00rootroot00000000000000usr/lib/python2*/dist-packages/dfdatetime/*.py usr/lib/python2*/dist-packages/dfdatetime*.egg-info/* dfdatetime-20180110/config/dpkg/python3-dfdatetime.install000066400000000000000000000001451322532640600233530ustar00rootroot00000000000000usr/lib/python3*/dist-packages/dfdatetime/*.py usr/lib/python3*/dist-packages/dfdatetime*.egg-info/* dfdatetime-20180110/config/dpkg/rules000077500000000000000000000011531322532640600173330ustar00rootroot00000000000000#!/usr/bin/make -f %: dh $@ --buildsystem=python_distutils --with=python2,python3 .PHONY: override_dh_auto_clean override_dh_auto_clean: dh_auto_clean rm -rf build dfdatetime.egg-info/SOURCES.txt dfdatetime.egg-info/PKG-INFO .PHONY: override_dh_auto_build override_dh_auto_build: dh_auto_build set -ex; for python in $(shell py3versions -r); do \ $$python setup.py build; \ done; .PHONY: override_dh_auto_install override_dh_auto_install: dh_auto_install --destdir $(CURDIR) set -ex; for python in $(shell py3versions -r); do \ $$python setup.py install --root=$(CURDIR) --install-layout=deb; \ done; dfdatetime-20180110/config/dpkg/source/000077500000000000000000000000001322532640600175535ustar00rootroot00000000000000dfdatetime-20180110/config/dpkg/source/format000066400000000000000000000000141322532640600207610ustar00rootroot000000000000003.0 (quilt) dfdatetime-20180110/config/travis/000077500000000000000000000000001322532640600166365ustar00rootroot00000000000000dfdatetime-20180110/config/travis/install.sh000077500000000000000000000020401322532640600206370ustar00rootroot00000000000000#!/bin/bash # # Script to set up Travis-CI test VM. COVERALL_DEPENDENCIES="python-coverage python-coveralls python-docopt"; L2TBINARIES_DEPENDENCIES=""; L2TBINARIES_TEST_DEPENDENCIES="funcsigs mock pbr six"; PYTHON2_DEPENDENCIES=""; PYTHON2_TEST_DEPENDENCIES="python-mock python-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}; elif test ${TRAVIS_OS_NAME} = "linux"; then sudo rm -f /etc/apt/sources.list.d/travis_ci_zeromq3-source.list; 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}; fi dfdatetime-20180110/dependencies.ini000066400000000000000000000000001322532640600171760ustar00rootroot00000000000000dfdatetime-20180110/dfdatetime.ini000066400000000000000000000006141322532640600166710ustar00rootroot00000000000000[project] name: dfdatetime name_description: dfDateTime maintainer: Log2Timeline maintainers homepage_url: https://github.com/log2timeline/dfdatetime description_short: Digital Forensics date and time (dfDateTime). description_long: dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision. dfdatetime-20180110/dfdatetime/000077500000000000000000000000001322532640600161675ustar00rootroot00000000000000dfdatetime-20180110/dfdatetime/__init__.py000066400000000000000000000003331322532640600202770ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Digital Forensics Date and Time (dfDateTime). dfDateTime, or Digital Forensics date and time, provides date and time objects to preserve accuracy and precision. """ __version__ = '20180110' dfdatetime-20180110/dfdatetime/cocoa_time.py000066400000000000000000000077231322532640600206540ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Cocoa timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class CocoaTime(interface.DateTimeValues): """Cocoa timestamp. The Cocoa timestamp is a floating point value that contains the number of seconds since 2001-01-01 00:00:00 (also known as the Cocoa epoch). Negative values represent date and times predating the Cocoa epoch. Also see: https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/ DatesAndTimes/Articles/dtDates.html 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. _COCOA_TO_POSIX_BASE = -978307200 def __init__(self, timestamp=None): """Initializes a Cocoa timestamp. Args: timestamp (Optional[float]): Cocoa timestamp. """ super(CocoaTime, self).__init__() self.precision = definitions.PRECISION_1_SECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a Cocoa timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', None) timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) timestamp += self._COCOA_TO_POSIX_BASE timestamp = float(timestamp) if microseconds is not None: timestamp += float(microseconds) / definitions.MICROSECONDS_PER_SECOND 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. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### """ if self.timestamp is None: return number_of_days, hours, minutes, seconds = self._GetTimeValues( int(self.timestamp)) year, month, day_of_month = self._GetDateValues( number_of_days, 2001, 1, 1) microseconds = int( (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. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self.timestamp is None: return timestamp = definitions.MICROSECONDS_PER_SECOND * ( self.timestamp - self._COCOA_TO_POSIX_BASE) return int(timestamp) dfdatetime-20180110/dfdatetime/decorators.py000066400000000000000000000014101322532640600207020ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Function decorators.""" from __future__ import unicode_literals import warnings def deprecated(function): """Decorator to mark functions or methods as deprecated.""" def IssueDeprecationWarning(*args, **kwargs): """Issue a deprecation warning.""" warnings.simplefilter('always', DeprecationWarning) warnings.warn('Call to deprecated function: {0:s}.'.format( function.__name__), category=DeprecationWarning, stacklevel=2) warnings.simplefilter('default', DeprecationWarning) return function(*args, **kwargs) IssueDeprecationWarning.__name__ = function.__name__ IssueDeprecationWarning.__doc__ = function.__doc__ IssueDeprecationWarning.__dict__.update(function.__dict__) return IssueDeprecationWarning dfdatetime-20180110/dfdatetime/definitions.py000066400000000000000000000017771322532640600210700ustar00rootroot00000000000000# -*- coding: utf-8 -*- """The date and time definitions. Also see: https://en.wikipedia.org/wiki/Day https://en.wikipedia.org/wiki/Hour https://en.wikipedia.org/wiki/Minute """ from __future__ import unicode_literals SECONDS_PER_DAY = 24 * 60 * 60 DECISECONDS_PER_SECOND = 10 MILLISECONDS_PER_SECOND = 1000 MICROSECONDS_PER_SECOND = 1000000 MICROSECONDS_PER_DECISECOND = 100000 MICROSECONDS_PER_MILLISECOND = 1000 PRECISION_1_DAY = '1d' PRECISION_1_HOUR = '1h' PRECISION_1_NANOSECOND = '1ns' PRECISION_100_NANOSECONDS = '100ns' PRECISION_1_MICROSECOND = '1us' PRECISION_1_MILLISECOND = '1ms' PRECISION_100_MILLISECONDS = '100ms' PRECISION_1_MINUTE = '1min' PRECISION_1_SECOND = '1s' PRECISION_2_SECONDS = '2s' PRECISION_VALUES = frozenset([ PRECISION_1_DAY, PRECISION_1_HOUR, PRECISION_1_NANOSECOND, PRECISION_100_NANOSECONDS, PRECISION_1_MICROSECOND, PRECISION_1_MILLISECOND, PRECISION_100_MILLISECONDS, PRECISION_1_MINUTE, PRECISION_1_SECOND, PRECISION_2_SECONDS]) dfdatetime-20180110/dfdatetime/delphi_date_time.py000066400000000000000000000106021322532640600220200ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Delphi TDateTime implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class DelphiDateTime(interface.DateTimeValues): """Delphi TDateTime timestamp. The Delphi TDateTime timestamp is a floating point value that contains the number of days since 1899-12-30 00:00:00 (also known as the epoch). Negative values represent date and times predating the epoch. The maximal correct date supported by TDateTime values is limited to: 9999-12-31 23:59:59.999 Also see: http://docwiki.embarcadero.com/Libraries/XE3/en/System.TDateTime 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. _DELPHI_TO_POSIX_BASE = 25569 # The number of microseconds per day. _MICROSECONDS_PER_DAY = 86400000000 def __init__(self, timestamp=None): """Initializes a Delphi TDateTime timestamp. Args: timestamp (Optional[float]): Delphi TDateTime timestamp. """ super(DelphiDateTime, self).__init__() self.precision = definitions.PRECISION_1_MILLISECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a Delphi TDateTime timestamp from a string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', None) if year > 9999: raise ValueError('Unsupported year value: {0:d}.'.format(year)) timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) 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 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. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### """ if self.timestamp is None: return 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) microseconds = int( (number_of_seconds % 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. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self.timestamp is None: return timestamp = ( (self.timestamp - self._DELPHI_TO_POSIX_BASE) * self._MICROSECONDS_PER_DAY) return int(timestamp) dfdatetime-20180110/dfdatetime/fake_time.py000066400000000000000000000073601322532640600204730ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Fake timestamp implementation.""" from __future__ import unicode_literals import time from dfdatetime import definitions from dfdatetime import interface class FakeTime(interface.DateTimeValues): """Fake timestamp. The fake timestamp is intended for testing purposes. On initialization it contains the current time in UTC in microsecond precision. 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. """ 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) self._microseconds = int( fraction_of_second * definitions.MICROSECONDS_PER_SECOND) self._number_of_seconds = int(timestamp) self.precision = definitions.PRECISION_1_MICROSECOND def CopyFromDateTimeString(self, time_string): """Copies a fake timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) 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. Returns: str: date and time value formatted as one of the following: YYYY-MM-DD hh:mm:ss YYYY-MM-DD hh:mm:ss.###### """ if self._number_of_seconds is None: return 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) if self._microseconds is None: return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( year, month, day_of_month, hours, minutes, seconds) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:06d}'.format( year, month, day_of_month, hours, minutes, seconds, self._microseconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self._number_of_seconds is None: return timestamp = self._number_of_seconds * definitions.MICROSECONDS_PER_SECOND if self._microseconds is None: return timestamp return timestamp + self._microseconds dfdatetime-20180110/dfdatetime/fat_date_time.py000066400000000000000000000130261322532640600213300ustar00rootroot00000000000000# -*- coding: utf-8 -*- """FAT date time implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class FATDateTime(interface.DateTimeValues): """FAT date time. The FAT date time is mainly used in DOS/Windows file formats and FAT. The FAT date and time is a 32-bit value containing two 16-bit values: * The date (lower 16-bit). * bits 0 - 4: day of month, where 1 represents the first day * bits 5 - 8: month of year, where 1 represent January * bits 9 - 15: year since 1980 * The time of day (upper 16-bit). * bits 0 - 4: seconds (in 2 second intervals) * bits 5 - 10: minutes * bits 11 - 15: hours The FAT date time has no time zone information and is typically stored in the local time of the computer. 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. """ # The difference between Jan 1, 1980 and Jan 1, 1970 in seconds. _FAT_DATE_TO_POSIX_BASE = 315532800 def __init__(self, fat_date_time=None): """Initializes a FAT date time. Args: fat_date_time (Optional[int]): FAT date time. """ number_of_seconds = None if fat_date_time is not None: number_of_seconds = self._GetNumberOfSeconds(fat_date_time) super(FATDateTime, self).__init__() self._number_of_seconds = number_of_seconds self.precision = definitions.PRECISION_2_SECONDS def _GetNumberOfSeconds(self, fat_date_time): """Retrieves the number of seconds from a FAT date time. Args: fat_date_time (int): FAT date time. Returns: int: number of seconds since January 1, 1980 00:00:00. Raises: ValueError: if the month, day of month, hours, minutes or seconds value is out of bounds. """ day_of_month = (fat_date_time & 0x1f) month = ((fat_date_time >> 5) & 0x0f) year = (fat_date_time >> 9) & 0x7f days_per_month = self._GetDaysPerMonth(year, month) if day_of_month < 1 or day_of_month > days_per_month: raise ValueError('Day of month value out of bounds.') number_of_days = self._GetDayOfYear(1980 + year, month, day_of_month) number_of_days -= 1 for past_year in range(0, year): number_of_days += self._GetNumberOfDaysInYear(past_year) fat_date_time >>= 16 seconds = (fat_date_time & 0x1f) * 2 minutes = (fat_date_time >> 5) & 0x3f hours = (fat_date_time >> 11) & 0x1f if hours not in range(0, 24): raise ValueError('Hours value out of bounds.') if minutes not in range(0, 60): raise ValueError('Minutes value out of bounds.') if seconds not in range(0, 60): raise ValueError('Seconds value out of bounds.') number_of_seconds = (((hours * 60) + minutes) * 60) + seconds number_of_seconds += number_of_days * definitions.SECONDS_PER_DAY return number_of_seconds def CopyFromDateTimeString(self, time_string): """Copies a FAT date time from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) if year < 1980 or year > (1980 + 0x7f): raise ValueError('Year value not supported: {0!s}.'.format(year)) self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self._number_of_seconds -= self._FAT_DATE_TO_POSIX_BASE self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the FAT date time 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 or self._number_of_seconds < 0: return None, None timestamp = self._number_of_seconds + self._FAT_DATE_TO_POSIX_BASE return timestamp, None def CopyToDateTimeString(self): """Copies the FAT date time to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss """ if self._number_of_seconds is None: return number_of_days, hours, minutes, seconds = self._GetTimeValues( self._number_of_seconds) year, month, day_of_month = self._GetDateValues(number_of_days, 1980, 1, 1) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( year, month, day_of_month, hours, minutes, seconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self._number_of_seconds is None or self._number_of_seconds < 0: return return definitions.MICROSECONDS_PER_SECOND * ( self._number_of_seconds + self._FAT_DATE_TO_POSIX_BASE) dfdatetime-20180110/dfdatetime/filetime.py000066400000000000000000000102241322532640600203360ustar00rootroot00000000000000# -*- coding: utf-8 -*- """FILETIME timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class Filetime(interface.DateTimeValues): """FILETIME timestamp. The FILETIME timestamp is a 64-bit integer that contains the number of 100th nano seconds since 1601-01-01 00:00:00. Do not confuse this with the FILETIME structure that consists of 2 x 32-bit integers and is presumed to be unsigned. 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 (int): FILETIME timestamp. """ # The difference between Jan 1, 1601 and Jan 1, 1970 in seconds. _FILETIME_TO_POSIX_BASE = 11644473600 _UINT64_MAX = (1 << 64) - 1 def __init__(self, timestamp=None): """Initializes a FILETIME timestamp. Args: timestamp (Optional[int]): FILETIME timestamp. """ super(Filetime, self).__init__() self.precision = definitions.PRECISION_100_NANOSECONDS self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a FILETIME timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) if year < 1601: raise ValueError('Year value not supported: {0!s}.'.format(year)) self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.timestamp += self._FILETIME_TO_POSIX_BASE self.timestamp *= definitions.MICROSECONDS_PER_SECOND self.timestamp += date_time_values.get('microseconds', 0) self.timestamp *= self._100NS_PER_MICROSECOND self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the FILETIME 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 or self.timestamp < 0 or self.timestamp > self._UINT64_MAX): return None, None timestamp, remainder = divmod(self.timestamp, self._100NS_PER_SECOND) timestamp -= self._FILETIME_TO_POSIX_BASE return timestamp, remainder def CopyToDateTimeString(self): """Copies the FILETIME timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.####### """ if (self.timestamp is None or self.timestamp < 0 or self.timestamp > self._UINT64_MAX): return timestamp, remainder = divmod(self.timestamp, self._100NS_PER_SECOND) number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1601, 1, 1) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:07d}'.format( year, month, day_of_month, hours, minutes, seconds, remainder) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if (self.timestamp is None or self.timestamp < 0 or self.timestamp > self._UINT64_MAX): return timestamp, _ = divmod(self.timestamp, self._100NS_PER_MICROSECOND) return timestamp - ( self._FILETIME_TO_POSIX_BASE * definitions.MICROSECONDS_PER_SECOND) dfdatetime-20180110/dfdatetime/hfs_time.py000066400000000000000000000072431322532640600203450ustar00rootroot00000000000000# -*- coding: utf-8 -*- """HFS timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class HFSTime(interface.DateTimeValues): """HFS timestamp. The HFS timestamp is an unsigned 32-bit integer that contains the number of seconds since 1904-01-01 00:00:00. Where in HFS the timestamp is typically in local time and in HFS+/HFSX in UTC. 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 (int): HFS timestamp. """ # The difference between Jan 1, 1904 and Jan 1, 1970 in seconds. _HFS_TO_POSIX_BASE = 2082844800 _UINT32_MAX = (1 << 32) - 1 def __init__(self, timestamp=None): """Initializes a HFS timestamp. Args: timestamp (Optional[int]): HFS timestamp. """ super(HFSTime, self).__init__() self.precision = definitions.PRECISION_1_SECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a HFS timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) if year < 1904 or year > 2040: raise ValueError('Year value not supported.') self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.timestamp += self._HFS_TO_POSIX_BASE self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the HFS 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 or self.timestamp < 0 or self.timestamp > self._UINT32_MAX): return None, None timestamp = self.timestamp - self._HFS_TO_POSIX_BASE return timestamp, 0 def CopyToDateTimeString(self): """Copies the HFS timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss """ if (self.timestamp is None or self.timestamp < 0 or self.timestamp > self._UINT32_MAX): return number_of_days, hours, minutes, seconds = self._GetTimeValues( self.timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1904, 1, 1) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( year, month, day_of_month, hours, minutes, seconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if (self.timestamp is None or self.timestamp < 0 or self.timestamp > self._UINT32_MAX): return timestamp = self.timestamp - self._HFS_TO_POSIX_BASE return timestamp * definitions.MICROSECONDS_PER_SECOND dfdatetime-20180110/dfdatetime/interface.py000066400000000000000000000451041322532640600205050ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Date and time values interface.""" from __future__ import unicode_literals import abc import calendar from dfdatetime import decorators class DateTimeValues(object): """Date time values interface. This is the super class of different date and time representations. 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. """ _DAYS_PER_MONTH = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) _100NS_PER_SECOND = 10000000 _100NS_PER_DECISECOND = 1000000 _100NS_PER_MILLISECOND = 10000 _100NS_PER_MICROSECOND = 10 _INT64_MIN = -(1 << 63) _INT64_MAX = (1 << 63) - 1 def __init__(self): """Initializes date time values.""" super(DateTimeValues, self).__init__() self.is_local_time = False self.precision = None def _AdjustForTimeZoneOffset( self, year, month, day_of_month, hours, minutes, time_zone_offset): """Adjusts the date and time values for a time zone offset. Args: year (int): year. month (int): month. day_of_month (int): day of month. hours (int): hours. minutes (int): minutes. time_zone_offset (int): time zone offset in number of minutes from UTC. Returns: tuple[int, int, int, int, int, int]: time zone correct year, month, day_of_month, hours and minutes values. """ hours_from_utc, minutes_from_utc = divmod(time_zone_offset, 60) minutes += minutes_from_utc # Since divmod makes sure the sign of minutes_from_utc is positive # we only need to check the upper bound here, because hours_from_utc # remains signed it is corrected accordingly. if minutes >= 60: minutes -= 60 hours += 1 hours += hours_from_utc if hours < 0: hours += 24 day_of_month -= 1 elif hours >= 24: hours -= 24 day_of_month += 1 days_per_month = self._GetDaysPerMonth(year, month) if day_of_month < 1: month -= 1 if month < 1: month = 12 year -= 1 day_of_month += self._GetDaysPerMonth(year, month) elif day_of_month > days_per_month: month += 1 if month > 12: month = 1 year += 1 day_of_month -= days_per_month return year, month, day_of_month, hours, minutes def _CopyDateFromString(self, date_string): """Copies a date from a string. Args: date_string (str): date value formatted as: YYYY-MM-DD Returns: tuple[int, int, int]: year, month, day of month. Raises: ValueError: if the date string is invalid or not supported. """ date_string_length = len(date_string) # The date string should at least contain 'YYYY-MM-DD'. if date_string_length < 10: raise ValueError('Date string too short.') if date_string[4] != '-' or date_string[7] != '-': raise ValueError('Invalid date string.') try: year = int(date_string[0:4], 10) except ValueError: raise ValueError('Unable to parse year.') try: month = int(date_string[5:7], 10) except ValueError: raise ValueError('Unable to parse month.') try: day_of_month = int(date_string[8:10], 10) except ValueError: raise ValueError('Unable to parse day of month.') days_per_month = self._GetDaysPerMonth(year, month) if day_of_month < 1 or day_of_month > days_per_month: raise ValueError('Day of month value out of bounds.') return year, month, day_of_month def _CopyDateTimeFromString(self, time_string): """Copies a date and time from a string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Returns: dict[str, int]: date and time values, such as year, month, day of month, hours, minutes, seconds, microseconds. Raises: ValueError: if the time string is invalid or not supported. """ if not time_string: raise ValueError('Invalid time string.') time_string_length = len(time_string) year, month, day_of_month = self._CopyDateFromString(time_string) if time_string_length <= 10: return { 'year': year, 'month': month, 'day_of_month': day_of_month} # If a time of day is specified the time string it should at least # contain 'YYYY-MM-DD hh:mm:ss'. if time_string[10] != ' ': raise ValueError( 'Invalid time string - space missing as date and time separator.') hours, minutes, seconds, microseconds, time_zone_offset = ( self._CopyTimeFromString(time_string[11:])) if time_zone_offset: year, month, day_of_month, hours, minutes = self._AdjustForTimeZoneOffset( year, month, day_of_month, hours, minutes, time_zone_offset) date_time_values = { 'year': year, 'month': month, 'day_of_month': day_of_month, 'hours': hours, 'minutes': minutes, 'seconds': seconds} if microseconds is not None: date_time_values['microseconds'] = microseconds return date_time_values def _CopyTimeFromString(self, time_string): """Copies a time from a string. Args: time_string (str): time value formatted as: hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The seconds fraction and time zone offset are optional. Returns: tuple[int, int, int, int, int]: hours, minutes, seconds, microseconds, time zone offset in minutes. Raises: ValueError: if the time string is invalid or not supported. """ time_string_length = len(time_string) # The time string should at least contain 'hh:mm:ss'. if time_string_length < 8: raise ValueError('Time string too short.') if time_string[2] != ':' or time_string[5] != ':': raise ValueError('Invalid time string.') try: hours = int(time_string[0:2], 10) except ValueError: raise ValueError('Unable to parse hours.') if hours not in range(0, 24): raise ValueError('Hours value: {0:d} out of bounds.'.format(hours)) try: minutes = int(time_string[3:5], 10) except ValueError: raise ValueError('Unable to parse minutes.') if minutes not in range(0, 60): raise ValueError('Minutes value: {0:d} out of bounds.'.format(minutes)) try: seconds = int(time_string[6:8], 10) except ValueError: raise ValueError('Unable to parse day of seconds.') # TODO: support a leap second? if seconds not in range(0, 60): raise ValueError('Seconds value: {0:d} out of bounds.'.format(seconds)) microseconds = None time_zone_offset = None time_zone_string_index = 8 while time_zone_string_index < time_string_length: if time_string[time_zone_string_index] in ('+', '-'): break time_zone_string_index += 1 # The calculations that follow rely on the time zone string index # to point beyond the string in case no time zone offset was defined. if time_zone_string_index == time_string_length - 1: time_zone_string_index += 1 if time_string_length > 8 and time_string[8] == '.': time_fraction_length = time_zone_string_index - 9 if time_fraction_length not in (3, 6): raise ValueError('Invalid time string.') try: time_fraction = time_string[9:time_zone_string_index] time_fraction = int(time_fraction, 10) except ValueError: raise ValueError('Unable to parse time fraction.') if time_fraction_length == 3: time_fraction *= 1000 microseconds = time_fraction if time_zone_string_index < time_string_length: if (time_string_length - time_zone_string_index != 6 or time_string[time_zone_string_index + 3] != ':'): raise ValueError('Invalid time string.') try: hours_from_utc = int(time_string[ time_zone_string_index + 1:time_zone_string_index + 3]) except ValueError: raise ValueError('Unable to parse time zone hours offset.') if hours_from_utc not in range(0, 15): raise ValueError('Time zone hours offset value out of bounds.') try: minutes_from_utc = int(time_string[ time_zone_string_index + 4:time_zone_string_index + 6]) except ValueError: raise ValueError('Unable to parse time zone minutes offset.') if minutes_from_utc not in range(0, 60): raise ValueError('Time zone minutes offset value out of bounds.') # pylint: disable=invalid-unary-operand-type time_zone_offset = (hours_from_utc * 60) + minutes_from_utc # Note that when the sign of the time zone offset is negative # the difference needs to be added. We do so by flipping the sign. if time_string[time_zone_string_index] != '-': time_zone_offset = -time_zone_offset return hours, minutes, seconds, microseconds, time_zone_offset def _GetDateValues( self, number_of_days, epoch_year, epoch_month, epoch_day_of_month): """Determines date values. Args: number_of_days (int): number of days since epoch. epoch_year (int): year that is the start of the epoch. epoch_month (int): month that is the start of the epoch. epoch_day_of_month (int): day of month that is the start of the epoch. Return: tuple[int, int, int]: year, month, day of month. Raises: ValueError: if the epoch year, month or day of month values are out of bounds. """ if epoch_year < 0: raise ValueError('Epoch year value out of bounds.') if epoch_month not in range(1, 13): raise ValueError('Epoch month value out of bounds.') epoch_days_per_month = self._GetDaysPerMonth(epoch_year, epoch_month) if epoch_day_of_month < 1 or epoch_day_of_month > epoch_days_per_month: raise ValueError('Epoch day of month value out of bounds.') before_epoch = number_of_days < 0 year = epoch_year month = epoch_month if before_epoch: month -= 1 if month <= 0: month = 12 year -= 1 number_of_days += epoch_day_of_month if before_epoch: number_of_days *= -1 # Align with the start of the year. while month > 1: days_per_month = self._GetDaysPerMonth(year, month) if number_of_days < days_per_month: break if before_epoch: month -= 1 else: month += 1 if month > 12: month = 1 year += 1 number_of_days -= days_per_month # Align with the start of the next century. _, remainder = divmod(year, 100) for _ in range(remainder, 100): days_in_year = self._GetNumberOfDaysInYear(year) if number_of_days < days_in_year: break if before_epoch: year -= 1 else: year += 1 number_of_days -= days_in_year days_in_century = self._GetNumberOfDaysInCentury(year) while number_of_days > days_in_century: if before_epoch: year -= 100 else: year += 100 number_of_days -= days_in_century days_in_century = self._GetNumberOfDaysInCentury(year) days_in_year = self._GetNumberOfDaysInYear(year) while number_of_days > days_in_year: if before_epoch: year -= 1 else: year += 1 number_of_days -= days_in_year days_in_year = self._GetNumberOfDaysInYear(year) days_per_month = self._GetDaysPerMonth(year, month) while number_of_days > days_per_month: if before_epoch: month -= 1 else: month += 1 if month <= 0: month = 12 year -= 1 elif month > 12: month = 1 year += 1 number_of_days -= days_per_month days_per_month = self._GetDaysPerMonth(year, month) if before_epoch: days_per_month = self._GetDaysPerMonth(year, month) number_of_days = days_per_month - number_of_days return year, month, number_of_days def _GetDayOfYear(self, year, month, day_of_month): """Retrieves the day of the year for a specific day of a month in a year. Args: year (int): year e.g. 1970. month (int): month where 1 represents January. day_of_month (int): day of the month where 1 represents the first day. Returns: int: day of year. Raises: ValueError: if the month or day of month value is out of bounds. """ if month not in range(1, 13): raise ValueError('Month value out of bounds.') days_per_month = self._GetDaysPerMonth(year, month) if day_of_month < 1 or day_of_month > days_per_month: raise ValueError('Day of month value out of bounds.') day_of_year = day_of_month for past_month in range(1, month): day_of_year += self._GetDaysPerMonth(year, past_month) return day_of_year def _GetDaysPerMonth(self, year, month): """Retrieves the number of days in a month of a specific year. Args: year (int): year e.g. 1970. month (int): month ranging from 1 to 12. Returns: int: number of days in the month. Raises: ValueError: if the month value is out of bounds. """ if month not in range(1, 13): raise ValueError('Month value out of bounds.') days_per_month = self._DAYS_PER_MONTH[month - 1] if month == 2 and self._IsLeapYear(year): days_per_month += 1 return days_per_month def _GetNumberOfDaysInCentury(self, year): """Retrieves the number of days in a century. Args: year (int): year in the century e.g. 1970. Returns: int: number of (remaining) days in the century. Raises: ValueError: if the year value is out of bounds. """ if year < 0: raise ValueError('Year value out of bounds.') year, _ = divmod(year, 100) if self._IsLeapYear(year): return 36525 return 36524 def _GetNumberOfDaysInYear(self, year): """Retrieves the number of days in a specific year. Args: year (int): year e.g. 1970. Returns: int: number of days in the year. """ if self._IsLeapYear(year): return 366 return 365 def _GetNumberOfSecondsFromElements( self, year, month, day_of_month, hours, minutes, seconds): """Retrieves the number of seconds from the date and time elements. Args: year (int): year e.g. 1970. month (int): month of year. day_of_month (int): day of month. hours (int): hours. minutes (int): minutes. seconds (int): seconds. Returns: int: number of seconds since January 1, 1970 00:00:00 or None. Raises: ValueError: if the time elements are invalid. """ if not year or not month or not day_of_month: return # calendar.timegm does not sanity check the time elements. if hours is None: hours = 0 elif hours not in range(0, 24): raise ValueError('Hours value: {0!s} out of bounds.'.format(hours)) if minutes is None: minutes = 0 elif minutes not in range(0, 60): raise ValueError('Minutes value: {0!s} out of bounds.'.format(minutes)) # TODO: support a leap second? if seconds is None: seconds = 0 elif seconds not in range(0, 60): raise ValueError('Seconds value: {0!s} out of bounds.'.format(seconds)) # Note that calendar.timegm() does not raise when date is: 2013-02-29. days_per_month = self._GetDaysPerMonth(year, month) if day_of_month < 1 or day_of_month > days_per_month: raise ValueError('Day of month value out of bounds.') # calendar.timegm requires the time tuple to contain at least # 6 integer values. time_elements_tuple = (year, month, day_of_month, hours, minutes, seconds) number_of_seconds = calendar.timegm(time_elements_tuple) return int(number_of_seconds) def _GetTimeValues(self, number_of_seconds): """Determines time values. Args: number_of_seconds (int): number of seconds. Return: tuple[int, int, int, int]: days, hours, minutes, seconds. """ number_of_minutes, seconds = divmod(number_of_seconds, 60) number_of_hours, minutes = divmod(number_of_minutes, 60) number_of_days, hours = divmod(number_of_hours, 24) return number_of_days, hours, minutes, seconds def _IsLeapYear(self, year): """Determines if a year is a leap year. Args: year (int): year e.g. 1970. Returns: bool: True if the year is a leap year. """ # pylint: disable=consider-using-ternary return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 @decorators.deprecated def CopyFromString(self, time_string): """Copies a date time value from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ self.CopyFromDateTimeString(time_string) @abc.abstractmethod def CopyFromDateTimeString(self, time_string): """Copies a date time value from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ @abc.abstractmethod def CopyToStatTimeTuple(self): """Copies the date time value 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. """ @abc.abstractmethod def CopyToDateTimeString(self): """Copies the date time value to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### """ # TODO: remove this method when there is no more need for it in plaso. @abc.abstractmethod def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ dfdatetime-20180110/dfdatetime/java_time.py000066400000000000000000000076611322532640600205120ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Java java.util.Date timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class JavaTime(interface.DateTimeValues): """Java java.util.Date timestamp. The Java java.util.Date timestamp is a signed integer that contains the number of milliseconds since 1970-01-01 00:00:00 (also known as the POSIX epoch). Negative values represent date and times predating the POSIX epoch. Also see: https://docs.oracle.com/javase/8/docs/api/java/util/Date.html 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 (int): Java timestamp. """ def __init__(self, timestamp=None): """Initializes a Java timestamp. Args: timestamp (Optional[int]): Java timestamp. """ super(JavaTime, self).__init__() self.precision = definitions.PRECISION_1_MILLISECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a Java timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', None) self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.timestamp *= definitions.MILLISECONDS_PER_SECOND if microseconds: milliseconds, _ = divmod( microseconds, definitions.MILLISECONDS_PER_SECOND) self.timestamp += milliseconds self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the Java 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 or self.timestamp < self._INT64_MIN or self.timestamp > self._INT64_MAX): return None, None timestamp, milliseconds = divmod( self.timestamp, definitions.MILLISECONDS_PER_SECOND) return timestamp, milliseconds * self._100NS_PER_MILLISECOND def CopyToDateTimeString(self): """Copies the Java timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.### """ if (self.timestamp is None or self.timestamp < self._INT64_MIN or self.timestamp > self._INT64_MAX): return timestamp, milliseconds = divmod( self.timestamp, definitions.MILLISECONDS_PER_SECOND) number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1970, 1, 1) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:03d}'.format( year, month, day_of_month, hours, minutes, seconds, milliseconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if (self.timestamp is None or self.timestamp < self._INT64_MIN or self.timestamp > self._INT64_MAX): return return self.timestamp * definitions.MICROSECONDS_PER_MILLISECOND dfdatetime-20180110/dfdatetime/ole_automation_date.py000066400000000000000000000105261322532640600225610ustar00rootroot00000000000000# -*- coding: utf-8 -*- """OLE automation date (or Floatingtime or Application time) implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class OLEAutomationDate(interface.DateTimeValues): """OLE Automation date. The OLE Automation date is a floating point value that contains the number of days since 1899-12-30 (also known as the OLE Automation date epoch), and the fractional part represents the fraction of a day since midnight. Negative values represent date and times predating the OLE Automation date epoch. Also see: https://msdn.microsoft.com/en-us/library/system.datetime.tooadate(v=vs.110).aspx 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): OLE Automation date. """ # The difference between Dec 30, 1899 and Jan 1, 1970 in days. _OLE_AUTOMATION_DATE_TO_POSIX_BASE = 25569 def __init__(self, timestamp=None): """Initializes an OLE Automation date. Args: timestamp (Optional[float]): OLE Automation date. """ super(OLEAutomationDate, self).__init__() self.precision = definitions.PRECISION_1_MICROSECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies an OLE Automation date from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', None) timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) timestamp = float(timestamp) if microseconds is not None: timestamp += float(microseconds) / definitions.MICROSECONDS_PER_SECOND timestamp /= definitions.SECONDS_PER_DAY timestamp += self._OLE_AUTOMATION_DATE_TO_POSIX_BASE self.timestamp = timestamp self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the OLE Automation date 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._OLE_AUTOMATION_DATE_TO_POSIX_BASE timestamp *= definitions.SECONDS_PER_DAY remainder = int((timestamp % 1) * self._100NS_PER_SECOND) return int(timestamp), remainder def CopyToDateTimeString(self): """Copies the OLE Automation date to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### """ if self.timestamp is None: return timestamp = self.timestamp * definitions.SECONDS_PER_DAY number_of_days, hours, minutes, seconds = self._GetTimeValues( int(timestamp)) year, month, day_of_month = self._GetDateValues( number_of_days, 1899, 12, 30) microseconds = int((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. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self.timestamp is None: return timestamp = self.timestamp - self._OLE_AUTOMATION_DATE_TO_POSIX_BASE timestamp *= definitions.SECONDS_PER_DAY timestamp *= definitions.MICROSECONDS_PER_SECOND return int(timestamp) dfdatetime-20180110/dfdatetime/posix_time.py000066400000000000000000000145111322532640600207230ustar00rootroot00000000000000# -*- coding: utf-8 -*- """POSIX timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class PosixTime(interface.DateTimeValues): """POSIX timestamp. The POSIX timestamp is a signed integer that contains the number of seconds since 1970-01-01 00:00:00 (also known as the POSIX epoch). Negative values represent date and times predating the POSIX epoch. The POSIX timestamp was initially 32-bit though 64-bit variants are known to be used. 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 (int): POSIX timestamp. """ def __init__(self, timestamp=None): """Initializes a POSIX timestamp. Args: timestamp (Optional[int]): POSIX timestamp. """ super(PosixTime, self).__init__() self.precision = definitions.PRECISION_1_SECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a POSIX timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the POSIX 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 return self.timestamp, None def CopyToDateTimeString(self): """Copies the POSIX timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss """ if self.timestamp is None: return number_of_days, hours, minutes, seconds = self._GetTimeValues( self.timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1970, 1, 1) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( year, month, day_of_month, hours, minutes, seconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self.timestamp is None: return return self.timestamp * definitions.MICROSECONDS_PER_SECOND class PosixTimeInMicroseconds(interface.DateTimeValues): """POSIX timestamp in microseconds. Variant of the POSIX timestamp in microseconds. 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 (int): POSIX timestamp in microseconds. """ def __init__(self, timestamp=None): """Initializes a POSIX timestamp in microseconds. Args: timestamp (Optional[int]): POSIX timestamp in microseconds. """ super(PosixTimeInMicroseconds, self).__init__() self.precision = definitions.PRECISION_1_MICROSECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a POSIX timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', 0) self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.timestamp *= definitions.MICROSECONDS_PER_SECOND self.timestamp += microseconds self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the POSIX 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, microseconds = divmod( self.timestamp, definitions.MICROSECONDS_PER_SECOND) return timestamp, microseconds * self._100NS_PER_MICROSECOND def CopyToDateTimeString(self): """Copies the POSIX timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### """ if self.timestamp is None: return timestamp, microseconds = divmod( self.timestamp, definitions.MICROSECONDS_PER_SECOND) number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1970, 1, 1) 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. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self.timestamp is None: return return self.timestamp dfdatetime-20180110/dfdatetime/precisions.py000066400000000000000000000174411322532640600207260ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Date and time precision helpers.""" from __future__ import unicode_literals from dfdatetime import definitions class DateTimePrecisionHelper(object): """Date time precision helper interface. This is the super class of different date and time precision helpers. Time precision helpers provide functionality for converting date and time values between different precisions. """ @classmethod def CopyMicrosecondsToFractionOfSecond(cls, microseconds): """Copies the number of microseconds to a fraction of second value. Args: microseconds (int): number of microseconds. Returns: float: fraction of second, which must be a value between 0.0 and 1.0. """ raise NotImplementedError() @classmethod def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): """Copies the time elements and fraction of second to a string. Args: time_elements_tuple (tuple[int, int, int, int, int, int]): time elements, contains year, month, day of month, hours, minutes and seconds. fraction_of_second (float): fraction of second, which must be a value between 0.0 and 1.0. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss with fraction of second part that corresponds to the precision. """ raise NotImplementedError() class SecondsPrecisionHelper(DateTimePrecisionHelper): """Seconds precision helper.""" @classmethod def CopyMicrosecondsToFractionOfSecond(cls, microseconds): """Copies the number of microseconds to a fraction of second value. Args: microseconds (int): number of microseconds. Returns: float: fraction of second, which must be a value between 0.0 and 1.0. For the seconds precision helper this will always be 0.0. Raises: ValueError: if the number of microseconds is out of bounds. """ if microseconds < 0 or microseconds >= definitions.MICROSECONDS_PER_SECOND: raise ValueError( 'Number of microseconds value: {0:d} out of bounds.'.format( microseconds)) return 0.0 @classmethod def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): """Copies the time elements and fraction of second to a string. Args: time_elements_tuple (tuple[int, int, int, int, int, int]): time elements, contains year, month, day of month, hours, minutes and seconds. fraction_of_second (float): fraction of second, which must be a value between 0.0 and 1.0. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss Raises: ValueError: if the fraction of second is out of bounds. """ if fraction_of_second < 0.0 or fraction_of_second >= 1.0: raise ValueError('Fraction of second value: {0:f} out of bounds.'.format( fraction_of_second)) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( time_elements_tuple[0], time_elements_tuple[1], time_elements_tuple[2], time_elements_tuple[3], time_elements_tuple[4], time_elements_tuple[5]) class MillisecondsPrecisionHelper(DateTimePrecisionHelper): """Milliseconds precision helper.""" @classmethod def CopyMicrosecondsToFractionOfSecond(cls, microseconds): """Copies the number of microseconds to a fraction of second value. Args: microseconds (int): number of microseconds. Returns: float: fraction of second, which must be a value between 0.0 and 1.0. Raises: ValueError: if the number of microseconds is out of bounds. """ if microseconds < 0 or microseconds >= definitions.MICROSECONDS_PER_SECOND: raise ValueError( 'Number of microseconds value: {0:d} out of bounds.'.format( microseconds)) milliseconds, _ = divmod( microseconds, definitions.MICROSECONDS_PER_MILLISECOND) return float(milliseconds) / definitions.MILLISECONDS_PER_SECOND @classmethod def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): """Copies the time elements and fraction of second to a string. Args: time_elements_tuple (tuple[int, int, int, int, int, int]): time elements, contains year, month, day of month, hours, minutes and seconds. fraction_of_second (float): fraction of second, which must be a value between 0.0 and 1.0. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.### Raises: ValueError: if the fraction of second is out of bounds. """ if fraction_of_second < 0.0 or fraction_of_second >= 1.0: raise ValueError('Fraction of second value: {0:f} out of bounds.'.format( fraction_of_second)) milliseconds = int(fraction_of_second * definitions.MILLISECONDS_PER_SECOND) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:03d}'.format( time_elements_tuple[0], time_elements_tuple[1], time_elements_tuple[2], time_elements_tuple[3], time_elements_tuple[4], time_elements_tuple[5], milliseconds) class MicrosecondsPrecisionHelper(DateTimePrecisionHelper): """Microseconds precision helper.""" @classmethod def CopyMicrosecondsToFractionOfSecond(cls, microseconds): """Copies the number of microseconds to a fraction of second value. Args: microseconds (int): number of microseconds. Returns: float: fraction of second, which must be a value between 0.0 and 1.0. Raises: ValueError: if the number of microseconds is out of bounds. """ if microseconds < 0 or microseconds >= definitions.MICROSECONDS_PER_SECOND: raise ValueError( 'Number of microseconds value: {0:d} out of bounds.'.format( microseconds)) return float(microseconds) / definitions.MICROSECONDS_PER_SECOND @classmethod def CopyToDateTimeString(cls, time_elements_tuple, fraction_of_second): """Copies the time elements and fraction of second to a string. Args: time_elements_tuple (tuple[int, int, int, int, int, int]): time elements, contains year, month, day of month, hours, minutes and seconds. fraction_of_second (float): fraction of second, which must be a value between 0.0 and 1.0. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### Raises: ValueError: if the fraction of second is out of bounds. """ if fraction_of_second < 0.0 or fraction_of_second >= 1.0: raise ValueError('Fraction of second value: {0:f} out of bounds.'.format( fraction_of_second)) microseconds = int(fraction_of_second * definitions.MICROSECONDS_PER_SECOND) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:06d}'.format( time_elements_tuple[0], time_elements_tuple[1], time_elements_tuple[2], time_elements_tuple[3], time_elements_tuple[4], time_elements_tuple[5], microseconds) class PrecisionHelperFactory(object): """Date time precision helper factory.""" _PRECISION_CLASSES = { definitions.PRECISION_1_MICROSECOND: MicrosecondsPrecisionHelper, definitions.PRECISION_1_MILLISECOND: MillisecondsPrecisionHelper, definitions.PRECISION_1_SECOND: SecondsPrecisionHelper, } @classmethod def CreatePrecisionHelper(cls, precision): """Creates a precision helper. Args: precision (str): precision of the date and time value, which should be one of the PRECISION_VALUES in definitions. Returns: class: date time precision helper class. Raises: ValueError: if the precision value is unsupported. """ precision_helper_class = cls._PRECISION_CLASSES.get(precision, None) if not precision_helper_class: raise ValueError('Unsupported precision: {0!s}'.format(precision)) return precision_helper_class dfdatetime-20180110/dfdatetime/rfc2579_date_time.py000066400000000000000000000155561322532640600216710ustar00rootroot00000000000000# -*- coding: utf-8 -*- """RFC2579 date-time implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class RFC2579DateTime(interface.DateTimeValues): """RFC2579 date-time. The RFC2579 date-time structure is 11 bytes of size and contains: struct { uin16_t year, uint8_t month, uint8_t day_of_month, uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t deciseconds, char direction_from_utc, uint8_t hours_from_utc, uint8_t minuted_from_utc } Also see: https://tools.ietf.org/html/rfc2579 Attributes: year (int): year, 0 through 65536. month (int): month of year, 1 through 12. day_of_month (int): day of month, 1 through 31. hours (int): hours, 0 through 23. minutes (int): minutes, 0 through 59. seconds (int): seconds, 0 through 59, where 60 is used to represent a leap-second. deciseconds (int): deciseconds, 0 through 9. """ def __init__(self, rfc2579_date_time_tuple=None): """Initializes a RFC2579 date-time. Args: rfc2579_date_time_tuple: (Optional[tuple[int, int, int, int, int, int, int]]): RFC2579 date-time time, contains year, month, day of month, hours, minutes, seconds and deciseconds. Raises: ValueError: if the system time is invalid. """ super(RFC2579DateTime, self).__init__() self._number_of_seconds = None self.day_of_month = None self.hours = None self.deciseconds = None self.minutes = None self.month = None self.precision = definitions.PRECISION_100_MILLISECONDS self.seconds = None self.year = None if rfc2579_date_time_tuple: if len(rfc2579_date_time_tuple) < 10: raise ValueError( 'Invalid RFC2579 date-time tuple 10 elements required.') if rfc2579_date_time_tuple[0] < 0 or rfc2579_date_time_tuple[0] > 65536: raise ValueError('Year value out of bounds.') if rfc2579_date_time_tuple[1] not in range(1, 13): raise ValueError('Month value out of bounds.') days_per_month = self._GetDaysPerMonth( rfc2579_date_time_tuple[0], rfc2579_date_time_tuple[1]) if (rfc2579_date_time_tuple[2] < 1 or rfc2579_date_time_tuple[2] > days_per_month): raise ValueError('Day of month value out of bounds.') if rfc2579_date_time_tuple[3] not in range(0, 24): raise ValueError('Hours value out of bounds.') if rfc2579_date_time_tuple[4] not in range(0, 60): raise ValueError('Minutes value out of bounds.') # TODO: support a leap second? if rfc2579_date_time_tuple[5] not in range(0, 60): raise ValueError('Seconds value out of bounds.') if rfc2579_date_time_tuple[6] < 0 or rfc2579_date_time_tuple[6] > 9: raise ValueError('Deciseconds value out of bounds.') if rfc2579_date_time_tuple[7] not in ('+', '-'): raise ValueError('Direction from UTC value out of bounds.') if rfc2579_date_time_tuple[8] not in range(0, 14): raise ValueError('Hours from UTC value out of bounds.') if rfc2579_date_time_tuple[9] not in range(0, 60): raise ValueError('Minutes from UTC value out of bounds.') time_zone_offset = ( (rfc2579_date_time_tuple[8] * 60) + rfc2579_date_time_tuple[9]) # Note that when the sign of the time zone offset is negative # the difference needs to be added. We do so by flipping the sign. if rfc2579_date_time_tuple[7] != '-': time_zone_offset = -time_zone_offset self.year, self.month, self.day_of_month, self.hours, self.minutes = ( self._AdjustForTimeZoneOffset( rfc2579_date_time_tuple[0], rfc2579_date_time_tuple[1], rfc2579_date_time_tuple[2], rfc2579_date_time_tuple[3], rfc2579_date_time_tuple[4], time_zone_offset)) self.deciseconds = rfc2579_date_time_tuple[6] self.seconds = rfc2579_date_time_tuple[5] self._number_of_seconds = self._GetNumberOfSecondsFromElements( self.year, self.month, self.day_of_month, self.hours, self.minutes, self.seconds) def CopyFromDateTimeString(self, time_string): """Copies a RFC2579 date-time from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the date string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', 0) deciseconds, _ = divmod( microseconds, definitions.MICROSECONDS_PER_DECISECOND) if year < 0 or year > 65536: raise ValueError('Unsupported year value: {0:d}.'.format(year)) self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.year = year self.month = month self.day_of_month = day_of_month self.hours = hours self.minutes = minutes self.seconds = seconds self.deciseconds = deciseconds self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the RFC2579 date-time 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 return self._number_of_seconds, ( self.deciseconds * self._100NS_PER_DECISECOND) def CopyToDateTimeString(self): """Copies the RFC2579 date-time to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.# """ if self._number_of_seconds is None: return return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:01d}'.format( self.year, self.month, self.day_of_month, self.hours, self.minutes, self.seconds, self.deciseconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self._number_of_seconds is None: return timestamp = self._number_of_seconds * definitions.DECISECONDS_PER_SECOND timestamp += self.deciseconds timestamp *= definitions.MICROSECONDS_PER_DECISECOND return timestamp dfdatetime-20180110/dfdatetime/semantic_time.py000066400000000000000000000050061322532640600213630ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Semantic time implementation.""" from __future__ import unicode_literals from dfdatetime import interface class SemanticTime(interface.DateTimeValues): """Semantic time. Semantic time is term to describe date and time values that have specific meaning such as: "Never", "Yesterday", "Not set". 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. string (str): semantic representation of the time, such as: "Never", "Not set". """ def __init__(self, string=None): """Initializes a semantic time. Args: string (str): semantic representation of the time, such as: "Never", "Not set". """ super(SemanticTime, self).__init__() self.string = string def CopyFromDateTimeString(self, time_string): """Copies semantic time from a date and time string. Args: time_string (str): semantic representation of the time, such as: "Never", "Not set". Raises: ValueError: because semantic time cannot be copied from a string. """ self.string = time_string def CopyToDateTimeString(self): """Copies the date time value to a date and time string. Returns: str: semantic representation of the time, such as: "Never", "Not set". """ return self.string def CopyToStatTimeTuple(self): """Copies the semantic timestamp to a stat timestamp tuple. Returns: tuple[int, int]: a POSIX timestamp in seconds and the remainder in 100 nano seconds, which will always be 0, 0. """ return 0, 0 def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds, which will always be 0. """ return 0 class InvalidTime(SemanticTime): """Semantic time that represents invalid.""" def __init__(self): """Initializes a semantic time that represents invalid.""" super(InvalidTime, self).__init__(string='Invalid') class Never(SemanticTime): """Semantic time that represents never.""" def __init__(self): """Initializes a semantic time that represents never.""" super(Never, self).__init__(string='Never') class NotSet(SemanticTime): """Semantic time that represents not set.""" def __init__(self): """Initializes a semantic time that represents not set.""" super(NotSet, self).__init__(string='Not set') dfdatetime-20180110/dfdatetime/systemtime.py000066400000000000000000000141021322532640600207420ustar00rootroot00000000000000# -*- coding: utf-8 -*- """SYSTEMTIME structure implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class Systemtime(interface.DateTimeValues): """SYSTEMTIME structure. The SYSTEMTIME structure is 16 bytes of size and contains: struct { WORD year, WORD month, WORD day_of_week, WORD day_of_month, WORD hour, WORD minute, WORD second, WORD millisecond } Attributes: year (int): year, 1601 through 30827. month (int): month of year, 1 through 12. day_of_week (int): day of week, 0 through 6. day_of_month (int): day of month, 1 through 31. hours (int): hours, 0 through 23. minutes (int): minutes, 0 through 59. seconds (int): seconds, 0 through 59. milliseconds (int): milliseconds, 0 through 999. """ def __init__(self, system_time_tuple=None): """Initializes a SYSTEMTIME structure. Args: system_time_tuple (Optional[tuple[int, int, int, int, int, int, int, int]]): system time, contains year, month, day of week, day of month, hours, minutes, seconds and milliseconds. Raises: ValueError: if the system time is invalid. """ super(Systemtime, self).__init__() self._number_of_seconds = None self.day_of_month = None self.day_of_week = None self.hours = None self.milliseconds = None self.minutes = None self.month = None self.precision = definitions.PRECISION_1_MILLISECOND self.seconds = None self.year = None if system_time_tuple: if len(system_time_tuple) < 8: raise ValueError('Invalid system time tuple 8 elements required.') if system_time_tuple[0] < 1601 or system_time_tuple[0] > 30827: raise ValueError('Year value out of bounds.') if system_time_tuple[1] not in range(1, 13): raise ValueError('Month value out of bounds.') if system_time_tuple[2] not in range(0, 7): raise ValueError('Day of week value out of bounds.') days_per_month = self._GetDaysPerMonth( system_time_tuple[0], system_time_tuple[1]) if system_time_tuple[3] < 1 or system_time_tuple[3] > days_per_month: raise ValueError('Day of month value out of bounds.') if system_time_tuple[4] not in range(0, 24): raise ValueError('Hours value out of bounds.') if system_time_tuple[5] not in range(0, 60): raise ValueError('Minutes value out of bounds.') # TODO: support a leap second? if system_time_tuple[6] not in range(0, 60): raise ValueError('Seconds value out of bounds.') if system_time_tuple[7] < 0 or system_time_tuple[7] > 999: raise ValueError('Milliseconds value out of bounds.') self.day_of_month = system_time_tuple[3] self.day_of_week = system_time_tuple[2] self.hours = system_time_tuple[4] self.milliseconds = system_time_tuple[7] self.minutes = system_time_tuple[5] self.month = system_time_tuple[1] self.seconds = system_time_tuple[6] self.year = system_time_tuple[0] self._number_of_seconds = self._GetNumberOfSecondsFromElements( self.year, self.month, self.day_of_month, self.hours, self.minutes, self.seconds) def CopyFromDateTimeString(self, time_string): """Copies a SYSTEMTIME structure from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the date string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', 0) milliseconds, _ = divmod( microseconds, definitions.MICROSECONDS_PER_MILLISECOND) if year < 1601 or year > 30827: raise ValueError('Unsupported year value: {0:d}.'.format(year)) self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.year = year self.month = month self.day_of_month = day_of_month # TODO: calculate day of week on demand. self.day_of_week = None self.hours = hours self.minutes = minutes self.seconds = seconds self.milliseconds = milliseconds self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the SYSTEMTIME structure 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 return self._number_of_seconds, ( self.milliseconds * self._100NS_PER_MILLISECOND) def CopyToDateTimeString(self): """Copies the SYSTEMTIME structure to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.### """ if self._number_of_seconds is None: return return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:03d}'.format( self.year, self.month, self.day_of_month, self.hours, self.minutes, self.seconds, self.milliseconds) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self._number_of_seconds is None: return timestamp = self._number_of_seconds * definitions.MILLISECONDS_PER_SECOND timestamp += self.milliseconds timestamp *= definitions.MICROSECONDS_PER_MILLISECOND return timestamp dfdatetime-20180110/dfdatetime/time_elements.py000066400000000000000000000617351322532640600214070ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Time elements implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface from dfdatetime import precisions class TimeElements(interface.DateTimeValues): """Time elements. Time elements contain separate values for year, month, day of month, hours, minutes and seconds. 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. """ def __init__(self, time_elements_tuple=None): """Initializes time elements. Args: time_elements_tuple (Optional[tuple[int, int, int, int, int, int]]): time elements, contains year, month, day of month, hours, minutes and seconds. Raises: ValueError: if the time elements tuple is invalid. """ super(TimeElements, self).__init__() self._number_of_seconds = None self._time_elements_tuple = time_elements_tuple self.precision = definitions.PRECISION_1_SECOND if time_elements_tuple: if len(time_elements_tuple) < 6: raise ValueError(( 'Invalid time elements tuple at least 6 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) self._number_of_seconds = self._GetNumberOfSecondsFromElements( *time_elements_tuple) def _CopyDateTimeFromStringISO8601(self, time_string): """Copies a date and time from an ISO 8601 date and time string. Args: time_string (str): time value formatted as: hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The fraction of second and time zone offset are optional. Returns: tuple[int, int, int, int, int]: hours, minutes, seconds, microseconds, time zone offset in minutes. Raises: ValueError: if the time string is invalid or not supported. """ if not time_string: raise ValueError('Invalid time string.') time_string_length = len(time_string) year, month, day_of_month = self._CopyDateFromString(time_string) if time_string_length <= 10: return { 'year': year, 'month': month, 'day_of_month': day_of_month} # If a time of day is specified the time string it should at least # contain 'YYYY-MM-DDThh'. if time_string[10] != 'T': raise ValueError( 'Invalid time string - missing as date and time separator.') hours, minutes, seconds, microseconds, time_zone_offset = ( self._CopyTimeFromStringISO8601(time_string[11:])) if time_zone_offset: year, month, day_of_month, hours, minutes = self._AdjustForTimeZoneOffset( year, month, day_of_month, hours, minutes, time_zone_offset) date_time_values = { 'year': year, 'month': month, 'day_of_month': day_of_month, 'hours': hours, 'minutes': minutes, 'seconds': seconds} if microseconds is not None: date_time_values['microseconds'] = microseconds return date_time_values def _CopyFromDateTimeValues(self, date_time_values): """Copies time elements from date and time values. Args: date_time_values (dict[str, int]): date and time values, such as year, month, day of month, hours, minutes, seconds, microseconds. """ year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self._time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds) self.is_local_time = False def _CopyTimeFromStringISO8601(self, time_string): """Copies a time from an ISO 8601 date and time string. Args: time_string (str): time value formatted as: hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The faction of second and time zone offset are optional. Returns: tuple[int, int, int, int, int]: hours, minutes, seconds, microseconds, time zone offset in minutes. Raises: ValueError: if the time string is invalid or not supported. """ if time_string.endswith('Z'): time_string = time_string[:-1] time_string_length = len(time_string) # The time string should at least contain 'hh'. if time_string_length < 2: raise ValueError('Time string too short.') try: hours = int(time_string[0:2], 10) except ValueError: raise ValueError('Unable to parse hours.') if hours not in range(0, 24): raise ValueError('Hours value: {0:d} out of bounds.'.format(hours)) minutes = None seconds = None microseconds = None time_zone_offset = None time_string_index = 2 # Minutes are either specified as 'hhmm', 'hh:mm' or as a fractional part # 'hh[.,]###'. if (time_string_index + 1 < time_string_length and time_string[time_string_index] not in ('.', ',')): if time_string[time_string_index] == ':': time_string_index += 1 if time_string_index + 2 > time_string_length: raise ValueError('Time string too short.') try: minutes = time_string[time_string_index:time_string_index + 2] minutes = int(minutes, 10) except ValueError: raise ValueError('Unable to parse minutes.') time_string_index += 2 # Seconds are either specified as 'hhmmss', 'hh:mm:ss' or as a fractional # part 'hh:mm[.,]###' or 'hhmm[.,]###'. if (time_string_index + 1 < time_string_length and time_string[time_string_index] not in ('.', ',')): if time_string[time_string_index] == ':': time_string_index += 1 if time_string_index + 2 > time_string_length: raise ValueError('Time string too short.') try: seconds = time_string[time_string_index:time_string_index + 2] seconds = int(seconds, 10) except ValueError: raise ValueError('Unable to parse day of seconds.') time_string_index += 2 time_zone_string_index = time_string_index while time_zone_string_index < time_string_length: if time_string[time_zone_string_index] in ('+', '-'): break time_zone_string_index += 1 # The calculations that follow rely on the time zone string index # to point beyond the string in case no time zone offset was defined. if time_zone_string_index == time_string_length - 1: time_zone_string_index += 1 if (time_string_length > time_string_index and time_string[time_string_index] in ('.', ',')): time_string_index += 1 time_fraction_length = time_zone_string_index - time_string_index try: time_fraction = time_string[time_string_index:time_zone_string_index] time_fraction = int(time_fraction, 10) time_fraction = float(time_fraction) / float(10 ** time_fraction_length) except ValueError: raise ValueError('Unable to parse time fraction.') if minutes is None: time_fraction *= 60 minutes = int(time_fraction) time_fraction -= minutes if seconds is None: time_fraction *= 60 seconds = int(time_fraction) time_fraction -= seconds time_fraction *= definitions.MICROSECONDS_PER_SECOND microseconds = int(time_fraction) if minutes is not None and minutes not in range(0, 60): raise ValueError('Minutes value: {0:d} out of bounds.'.format(minutes)) # TODO: support a leap second? if seconds is not None and seconds not in range(0, 60): raise ValueError('Seconds value: {0:d} out of bounds.'.format(seconds)) if time_zone_string_index < time_string_length: if (time_string_length - time_zone_string_index != 6 or time_string[time_zone_string_index + 3] != ':'): raise ValueError('Invalid time string.') try: hours_from_utc = int(time_string[ time_zone_string_index + 1:time_zone_string_index + 3]) except ValueError: raise ValueError('Unable to parse time zone hours offset.') if hours_from_utc not in range(0, 15): raise ValueError('Time zone hours offset value out of bounds.') try: minutes_from_utc = int(time_string[ time_zone_string_index + 4:time_zone_string_index + 6]) except ValueError: raise ValueError('Unable to parse time zone minutes offset.') if minutes_from_utc not in range(0, 60): raise ValueError('Time zone minutes offset value out of bounds.') # pylint: disable=invalid-unary-operand-type time_zone_offset = (hours_from_utc * 60) + minutes_from_utc # Note that when the sign of the time zone offset is negative # the difference needs to be added. We do so by flipping the sign. if time_string[time_zone_string_index] != '-': time_zone_offset = -time_zone_offset return hours, minutes, seconds, microseconds, time_zone_offset def CopyFromDateTimeString(self, time_string): """Copies time elements from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. """ date_time_values = self._CopyDateTimeFromString(time_string) self._CopyFromDateTimeValues(date_time_values) def CopyFromStringISO8601(self, time_string): """Copies time elements from an ISO 8601 date and time string. Currently not supported: * Duration notation: "P..." * Week notation "2016-W33" * Date with week number notation "2016-W33-3" * Date without year notation "--08-17" * Ordinal date notation "2016-230" Args: time_string (str): date and time value formatted as: YYYY-MM-DDThh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromStringISO8601(time_string) self._CopyFromDateTimeValues(date_time_values) 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]]): time elements, contains year, month, day of month, hours, minutes and seconds. Raises: ValueError: if the time elements tuple is invalid. """ if len(time_elements_tuple) < 6: raise ValueError(( 'Invalid time elements tuple at least 6 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) try: year = int(time_elements_tuple[0], 10) except (TypeError, ValueError): raise ValueError('Invalid year value: {0!s}'.format( time_elements_tuple[0])) try: month = int(time_elements_tuple[1], 10) except (TypeError, ValueError): raise ValueError('Invalid month value: {0!s}'.format( time_elements_tuple[1])) try: day_of_month = int(time_elements_tuple[2], 10) except (TypeError, ValueError): raise ValueError('Invalid day of month value: {0!s}'.format( time_elements_tuple[2])) try: hours = int(time_elements_tuple[3], 10) except (TypeError, ValueError): raise ValueError('Invalid hours value: {0!s}'.format( time_elements_tuple[3])) try: minutes = int(time_elements_tuple[4], 10) except (TypeError, ValueError): raise ValueError('Invalid minutes value: {0!s}'.format( time_elements_tuple[4])) try: seconds = int(time_elements_tuple[5], 10) except (TypeError, ValueError): raise ValueError('Invalid seconds value: {0!s}'.format( time_elements_tuple[5])) self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self._time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds) def CopyToStatTimeTuple(self): """Copies the time elements 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 return self._number_of_seconds, None def CopyToDateTimeString(self): """Copies the time elements to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss """ if self._number_of_seconds is None: return return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format( self._time_elements_tuple[0], self._time_elements_tuple[1], self._time_elements_tuple[2], self._time_elements_tuple[3], self._time_elements_tuple[4], self._time_elements_tuple[5]) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self._number_of_seconds is None: return return self._number_of_seconds * definitions.MICROSECONDS_PER_SECOND class TimeElementsWithFractionOfSecond(TimeElements): """Time elements with a fraction of second interface. Attributes: fraction_of_second (float): 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 and time value, which should be one of the PRECISION_VALUES in definitions. """ def __init__(self, fraction_of_second=None, time_elements_tuple=None): """Initializes time elements. Args: fraction_of_second (Optional[float]): fraction of second, which must be a value between 0.0 and 1.0. time_elements_tuple (Optional[tuple[int, int, int, int, int, int]]): time elements, contains year, month, day of month, hours, minutes and seconds. Raises: ValueError: if the time elements tuple is invalid or fraction of second value is out of bounds. """ if fraction_of_second is not None: if fraction_of_second < 0.0 or fraction_of_second >= 1.0: raise ValueError( 'Fraction of second value: {0:f} out of bounds.'.format( fraction_of_second)) super(TimeElementsWithFractionOfSecond, self).__init__( time_elements_tuple=time_elements_tuple) self.fraction_of_second = fraction_of_second self.precision = None def _CopyFromDateTimeValues(self, date_time_values): """Copies time elements from date and time values. Args: date_time_values (dict[str, int]): date and time values, such as year, month, day of month, hours, minutes, seconds, microseconds. Raises: ValueError: if no helper can be created for the current precision. """ year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) microseconds = date_time_values.get('microseconds', 0) precision_helper = precisions.PrecisionHelperFactory.CreatePrecisionHelper( self.precision) fraction_of_second = precision_helper.CopyMicrosecondsToFractionOfSecond( microseconds) self._number_of_seconds = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self._time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds) self.fraction_of_second = fraction_of_second self.is_local_time = False 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 fraction of seconds. Raises: ValueError: if the time elements tuple is invalid. """ if len(time_elements_tuple) < 7: raise ValueError(( 'Invalid time elements tuple at least 7 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) super(TimeElementsWithFractionOfSecond, self).CopyFromStringTuple( time_elements_tuple) try: fraction_of_second = float(time_elements_tuple[6]) except (TypeError, ValueError): raise ValueError('Invalid fraction of second value: {0!s}'.format( time_elements_tuple[6])) if fraction_of_second < 0.0 or fraction_of_second >= 1.0: raise ValueError('Fraction of second value: {0:f} out of bounds.'.format( fraction_of_second)) self.fraction_of_second = fraction_of_second def CopyToStatTimeTuple(self): """Copies the time elements 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 or self.fraction_of_second is None: return None, None return self._number_of_seconds, ( int(self.fraction_of_second * self._100NS_PER_SECOND)) def CopyToDateTimeString(self): """Copies the time elements to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.### or YYYY-MM-DD hh:mm:ss.###### Raises: ValueError: if the precision value is unsupported. """ if self._number_of_seconds is None or self.fraction_of_second is None: return precision_helper = precisions.PrecisionHelperFactory.CreatePrecisionHelper( self.precision) return precision_helper.CopyToDateTimeString( self._time_elements_tuple, self.fraction_of_second) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if self._number_of_seconds is None or self.fraction_of_second is None: return timestamp = self._number_of_seconds * definitions.MICROSECONDS_PER_SECOND timestamp += int( self.fraction_of_second * definitions.MICROSECONDS_PER_SECOND) return timestamp class TimeElementsInMilliseconds(TimeElementsWithFractionOfSecond): """Time elements in milliseconds. Attributes: fraction_of_second (float): 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 millisecond (PRECISION_1_MILLISECOND). """ def __init__(self, time_elements_tuple=None): """Initializes time elements. Args: time_elements_tuple (Optional[tuple[int, int, int, int, int, int, int]]): time elements, contains year, month, day of month, hours, minutes, seconds and milliseconds. Raises: ValueError: if the time elements tuple is invalid. """ fraction_of_second = None if time_elements_tuple: if len(time_elements_tuple) < 7: raise ValueError(( 'Invalid time elements tuple at least 7 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) milliseconds = time_elements_tuple[6] time_elements_tuple = time_elements_tuple[:6] if (milliseconds < 0 or milliseconds >= definitions.MILLISECONDS_PER_SECOND): raise ValueError('Invalid number of milliseconds.') fraction_of_second = ( float(milliseconds) / definitions.MILLISECONDS_PER_SECOND) super(TimeElementsInMilliseconds, self).__init__( fraction_of_second=fraction_of_second, time_elements_tuple=time_elements_tuple) self.precision = definitions.PRECISION_1_MILLISECOND @property def milliseconds(self): """int: number of milliseconds.""" return int(self.fraction_of_second * definitions.MILLISECONDS_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 milliseconds. Raises: ValueError: if the time elements tuple is invalid. """ if len(time_elements_tuple) < 7: raise ValueError(( 'Invalid time elements tuple at least 7 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) year, month, day_of_month, hours, minutes, seconds, milliseconds = ( time_elements_tuple) try: milliseconds = int(milliseconds, 10) except (TypeError, ValueError): raise ValueError('Invalid millisecond value: {0!s}'.format(milliseconds)) if milliseconds < 0 or milliseconds >= definitions.MILLISECONDS_PER_SECOND: raise ValueError('Invalid number of milliseconds.') fraction_of_second = ( float(milliseconds) / definitions.MILLISECONDS_PER_SECOND) time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds, str(fraction_of_second)) super(TimeElementsInMilliseconds, self).CopyFromStringTuple( time_elements_tuple) class TimeElementsInMicroseconds(TimeElementsWithFractionOfSecond): """Time elements in microseconds. Attributes: fraction_of_second (float): 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 microsecond (PRECISION_1_MICROSECOND). """ def __init__(self, time_elements_tuple=None): """Initializes time elements. Args: time_elements_tuple (Optional[tuple[int, int, int, int, int, int, int]]): time elements, contains year, month, day of month, hours, minutes, seconds and microseconds. Raises: ValueError: if the time elements tuple is invalid. """ fraction_of_second = None if time_elements_tuple: if len(time_elements_tuple) < 7: raise ValueError(( 'Invalid time elements tuple at least 7 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) microseconds = time_elements_tuple[6] time_elements_tuple = time_elements_tuple[:6] if (microseconds < 0 or microseconds >= definitions.MICROSECONDS_PER_SECOND): raise ValueError('Invalid number of microseconds.') fraction_of_second = ( float(microseconds) / definitions.MICROSECONDS_PER_SECOND) super(TimeElementsInMicroseconds, self).__init__( fraction_of_second=fraction_of_second, time_elements_tuple=time_elements_tuple) self.precision = definitions.PRECISION_1_MICROSECOND @property def microseconds(self): """int: number of microseconds.""" return int(self.fraction_of_second * definitions.MICROSECONDS_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 microseconds. Raises: ValueError: if the time elements tuple is invalid. """ if len(time_elements_tuple) < 7: raise ValueError(( 'Invalid time elements tuple at least 7 elements required,' 'got: {0:d}').format(len(time_elements_tuple))) year, month, day_of_month, hours, minutes, seconds, microseconds = ( time_elements_tuple) try: microseconds = int(microseconds, 10) except (TypeError, ValueError): raise ValueError('Invalid microsecond value: {0!s}'.format(microseconds)) if microseconds < 0 or microseconds >= definitions.MICROSECONDS_PER_SECOND: raise ValueError('Invalid number of microseconds.') fraction_of_second = ( float(microseconds) / definitions.MICROSECONDS_PER_SECOND) time_elements_tuple = ( year, month, day_of_month, hours, minutes, seconds, str(fraction_of_second)) super(TimeElementsInMicroseconds, self).CopyFromStringTuple( time_elements_tuple) dfdatetime-20180110/dfdatetime/uuid_time.py000066400000000000000000000104711322532640600205300ustar00rootroot00000000000000# -*- coding: utf-8 -*- """UUID version 1 timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class UUIDTime(interface.DateTimeValues): """UUID version 1 timestamp. The UUID version 1 timestamp is an unsigned 60-bit value that contains the number of 100th nano seconds intervals since 1582-10-15 00:00:00. Also see: https://en.wikipedia.org/wiki/Universally_unique_identifier 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 (int): UUID timestamp. """ # The difference between Oct 15, 1582 and Jan 1, 1970 in seconds. _UUID_TO_POSIX_BASE = 12219292800 _UINT60_MAX = (1 << 60) - 1 def __init__(self, timestamp=None): """Initializes an UUID version 1 timestamp. Args: timestamp (Optional[int]): UUID version 1 timestamp. Raises: ValueError: if the UUID version 1 timestamp is invalid. """ if timestamp and (timestamp < 0 or timestamp > self._UINT60_MAX): raise ValueError('Invalid UUID version 1 timestamp.') super(UUIDTime, self).__init__() self.precision = definitions.PRECISION_100_NANOSECONDS self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies an UUID timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) if year < 1582: raise ValueError('Year value not supported.') self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.timestamp += self._UUID_TO_POSIX_BASE self.timestamp *= definitions.MICROSECONDS_PER_SECOND self.timestamp += date_time_values.get('microseconds', 0) self.timestamp *= self._100NS_PER_MICROSECOND self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the UUID 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 or self.timestamp < 0 or self.timestamp > self._UINT60_MAX): return None, None timestamp, remainder = divmod(self.timestamp, self._100NS_PER_SECOND) timestamp -= self._UUID_TO_POSIX_BASE return timestamp, remainder def CopyToDateTimeString(self): """Copies the UUID timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.####### """ if (self.timestamp is None or self.timestamp < 0 or self.timestamp > self._UINT60_MAX): return timestamp, remainder = divmod(self.timestamp, self._100NS_PER_SECOND) number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1582, 10, 15) return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}.{6:07d}'.format( year, month, day_of_month, hours, minutes, seconds, remainder) def GetPlasoTimestamp(self): """Retrieves a timestamp that is compatible with plaso. Returns: int: a POSIX timestamp in microseconds or None on error. """ if (self.timestamp is None or self.timestamp < 0 or self.timestamp > self._UINT60_MAX): return timestamp, _ = divmod(self.timestamp, self._100NS_PER_MICROSECOND) timestamp -= self._UUID_TO_POSIX_BASE * definitions.MICROSECONDS_PER_SECOND return timestamp dfdatetime-20180110/dfdatetime/webkit_time.py000066400000000000000000000075521322532640600210550ustar00rootroot00000000000000# -*- coding: utf-8 -*- """WebKit timestamp implementation.""" from __future__ import unicode_literals from dfdatetime import definitions from dfdatetime import interface class WebKitTime(interface.DateTimeValues): """WebKit timestamp. The WebKit timestamp is a signed 64-bit integer that contains the number of micro seconds since 1601-01-01 00:00:00. 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. """ # The difference between Jan 1, 1601 and Jan 1, 1970 in seconds. _WEBKIT_TO_POSIX_BASE = 11644473600 def __init__(self, timestamp=None): """Initializes a WebKit timestamp. Args: timestamp (Optional[int]): WebKit timestamp. """ super(WebKitTime, self).__init__() self.precision = definitions.PRECISION_1_MICROSECOND self.timestamp = timestamp def CopyFromDateTimeString(self, time_string): """Copies a WebKit timestamp from a date and time string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Raises: ValueError: if the time string is invalid or not supported. """ date_time_values = self._CopyDateTimeFromString(time_string) year = date_time_values.get('year', 0) month = date_time_values.get('month', 0) day_of_month = date_time_values.get('day_of_month', 0) hours = date_time_values.get('hours', 0) minutes = date_time_values.get('minutes', 0) seconds = date_time_values.get('seconds', 0) self.timestamp = self._GetNumberOfSecondsFromElements( year, month, day_of_month, hours, minutes, seconds) self.timestamp += self._WEBKIT_TO_POSIX_BASE self.timestamp *= definitions.MICROSECONDS_PER_SECOND self.timestamp += date_time_values.get('microseconds', 0) self.is_local_time = False def CopyToStatTimeTuple(self): """Copies the WebKit 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 or self.timestamp < self._INT64_MIN or self.timestamp > self._INT64_MAX): return None, None timestamp, microseconds = divmod( self.timestamp, definitions.MICROSECONDS_PER_SECOND) timestamp -= self._WEBKIT_TO_POSIX_BASE return timestamp, microseconds * self._100NS_PER_MICROSECOND def CopyToDateTimeString(self): """Copies the WebKit timestamp to a date and time string. Returns: str: date and time value formatted as: YYYY-MM-DD hh:mm:ss.###### """ if (self.timestamp is None or self.timestamp < self._INT64_MIN or self.timestamp > self._INT64_MAX): return timestamp, microseconds = divmod( self.timestamp, definitions.MICROSECONDS_PER_SECOND) number_of_days, hours, minutes, seconds = self._GetTimeValues(timestamp) year, month, day_of_month = self._GetDateValues( number_of_days, 1601, 1, 1) 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. Returns: int: a POSIX timestamp in microseconds or None on error. """ if (self.timestamp is None or self.timestamp < self._INT64_MIN or self.timestamp > self._INT64_MAX): return return self.timestamp - ( self._WEBKIT_TO_POSIX_BASE * definitions.MICROSECONDS_PER_SECOND) dfdatetime-20180110/requirements.txt000066400000000000000000000000141322532640600173400ustar00rootroot00000000000000pip >= 7.0.0dfdatetime-20180110/run_tests.py000077500000000000000000000016351322532640600164710ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Script to run the tests.""" import sys import unittest # Change PYTHONPATH to include dependencies. sys.path.insert(0, '.') import utils.dependencies # pylint: disable=wrong-import-position if __name__ == '__main__': fail_unless_has_test_file = '--fail-unless-has-test-file' in sys.argv setattr(unittest, 'fail_unless_has_test_file', fail_unless_has_test_file) if fail_unless_has_test_file: # Remove --fail-unless-has-test-file otherwise it will conflict with # the argparse tests. sys.argv.remove('--fail-unless-has-test-file') dependency_helper = utils.dependencies.DependencyHelper() if not dependency_helper.CheckTestDependencies(): sys.exit(1) test_suite = unittest.TestLoader().discover('tests', pattern='*.py') test_results = unittest.TextTestRunner(verbosity=2).run(test_suite) if not test_results.wasSuccessful(): sys.exit(1) dfdatetime-20180110/setup.cfg000066400000000000000000000003431322532640600157020ustar00rootroot00000000000000[bdist_rpm] release = 1 packager = Log2Timeline maintainers doc_files = ACKNOWLEDGEMENTS AUTHORS LICENSE README build_requires = python-setuptools dfdatetime-20180110/setup.py000077500000000000000000000115461322532640600156050ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Installation and deployment script.""" from __future__ import print_function import sys try: from setuptools import find_packages, setup except ImportError: from distutils.core import find_packages, setup try: from distutils.command.bdist_msi import bdist_msi except ImportError: bdist_msi = None try: from distutils.command.bdist_rpm import bdist_rpm except ImportError: bdist_rpm = None if sys.version < '2.7': print('Unsupported Python version: {0:s}.'.format(sys.version)) print('Supported Python versions are 2.7 or a later 2.x version.') sys.exit(1) # Change PYTHONPATH to include dfdatetime so that we can get the version. sys.path.insert(0, '.') import dfdatetime # pylint: disable=wrong-import-position if not bdist_msi: BdistMSICommand = None else: class BdistMSICommand(bdist_msi): """Custom handler for the bdist_msi command.""" def run(self): """Builds an MSI.""" # Command bdist_msi does not support the library version, neither a date # as a version but if we suffix it with .1 everything is fine. self.distribution.metadata.version += '.1' bdist_msi.run(self) if not bdist_rpm: BdistRPMCommand = None else: class BdistRPMCommand(bdist_rpm): """Custom handler for the bdist_rpm command.""" def _make_spec_file(self): """Generates the text of an RPM spec file. Returns: list[str]: lines of the RPM spec file. """ # Note that bdist_rpm can be an old style class. if issubclass(BdistRPMCommand, object): spec_file = super(BdistRPMCommand, self)._make_spec_file() else: spec_file = bdist_rpm._make_spec_file(self) if sys.version_info[0] < 3: python_package = 'python' else: python_package = 'python3' description = [] summary = '' in_description = False python_spec_file = [] for line in iter(spec_file): if line.startswith('Summary: '): summary = line elif line.startswith('BuildRequires: '): line = 'BuildRequires: {0:s}-setuptools'.format(python_package) elif line.startswith('Requires: '): if python_package == 'python3': line = line.replace('python', 'python3') elif line.startswith('%description'): in_description = True elif line.startswith('%files'): # Cannot use %{_libdir} here since it can expand to "lib64". lines = [ '%files', '%defattr(644,root,root,755)', '%doc ACKNOWLEDGEMENTS AUTHORS LICENSE README', '%{_prefix}/lib/python*/site-packages/dfdatetime/*.py', '%{_prefix}/lib/python*/site-packages/dfdatetime*.egg-info/*', '%exclude %{_prefix}/lib/python*/site-packages/dfdatetime/*.pyc', '%exclude %{_prefix}/lib/python*/site-packages/dfdatetime/*.pyo', ('%exclude %{_prefix}/lib/python*/site-packages/dfdatetime/' '__pycache__/*')] python_spec_file.extend(lines) break elif line.startswith('%prep'): in_description = False python_spec_file.append( '%package -n {0:s}-%{{name}}'.format(python_package)) python_spec_file.append('{0:s}'.format(summary)) python_spec_file.append('') python_spec_file.append( '%description -n {0:s}-%{{name}}'.format(python_package)) python_spec_file.extend(description) elif in_description: # Ignore leading white lines in the description. if not description and not line: continue description.append(line) python_spec_file.append(line) return python_spec_file dfdatetime_description = ( 'Digital Forensics Date and Time (dfDateTime).') dfdatetime_long_description = ( 'dfDateTime, or Digital Forensics date and time, provides date and time ' 'objects to preserve accuracy and precision.') setup( name='dfdatetime', version=dfdatetime.__version__, description=dfdatetime_description, long_description=dfdatetime_long_description, license='Apache License, Version 2.0', url='https://github.com/log2timeline/dfdatetime', maintainer='dfDateTime development team', maintainer_email='log2timeline-dev@googlegroups.com', cmdclass={ 'bdist_msi': BdistMSICommand, 'bdist_rpm': BdistRPMCommand}, classifiers=[ 'Development Status :: 3 - Alpha', 'Environment :: Console', 'Operating System :: OS Independent', 'Programming Language :: Python', ], packages=find_packages('.', exclude=[ 'examples', 'tests', 'tests.*', 'utils']), package_dir={ 'dfdatetime': 'dfdatetime' }, data_files=[ ('share/doc/dfdatetime', [ 'ACKNOWLEDGEMENTS', 'AUTHORS', 'LICENSE', 'README']), ], ) dfdatetime-20180110/tests/000077500000000000000000000000001322532640600152235ustar00rootroot00000000000000dfdatetime-20180110/tests/__init__.py000066400000000000000000000000301322532640600173250ustar00rootroot00000000000000# -*- coding: utf-8 -*- dfdatetime-20180110/tests/cocoa_time.py000066400000000000000000000057571322532640600177150ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the Cocoa timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import cocoa_time class CocoaTimeTest(unittest.TestCase): """Tests for the Cocoa timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" cocoa_time_object = cocoa_time.CocoaTime() expected_timestamp = 394934400.0 cocoa_time_object.CopyFromDateTimeString('2013-07-08') self.assertEqual(cocoa_time_object.timestamp, expected_timestamp) expected_timestamp = 395011845.0 cocoa_time_object.CopyFromDateTimeString('2013-07-08 21:30:45') self.assertEqual(cocoa_time_object.timestamp, expected_timestamp) expected_timestamp = 395011845.546875 cocoa_time_object.CopyFromDateTimeString('2013-07-08 21:30:45.546875') self.assertEqual(cocoa_time_object.timestamp, expected_timestamp) expected_timestamp = 395015445.546875 cocoa_time_object.CopyFromDateTimeString('2013-07-08 21:30:45.546875-01:00') self.assertEqual(cocoa_time_object.timestamp, expected_timestamp) expected_timestamp = 395008245.546875 cocoa_time_object.CopyFromDateTimeString('2013-07-08 21:30:45.546875+01:00') self.assertEqual(cocoa_time_object.timestamp, expected_timestamp) expected_timestamp = 86400.0 cocoa_time_object.CopyFromDateTimeString('2001-01-02 00:00:00') self.assertEqual(cocoa_time_object.timestamp, expected_timestamp) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" cocoa_time_object = cocoa_time.CocoaTime(timestamp=395011845.0) expected_stat_time_tuple = (1373319045, 0) stat_time_tuple = cocoa_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) cocoa_time_object = cocoa_time.CocoaTime() expected_stat_time_tuple = (None, None) stat_time_tuple = cocoa_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" cocoa_time_object = cocoa_time.CocoaTime(timestamp=395011845.546875) date_time_string = cocoa_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2013-07-08 21:30:45.546875') cocoa_time_object = cocoa_time.CocoaTime() date_time_string = cocoa_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" cocoa_time_object = cocoa_time.CocoaTime(timestamp=395011845.0) expected_micro_posix_timestamp = 1373319045000000 micro_posix_timestamp = cocoa_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) cocoa_time_object = cocoa_time.CocoaTime() micro_posix_timestamp = cocoa_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/delphi_date_time.py000066400000000000000000000106361322532640600210630ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the Delphi TDateTime timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import delphi_date_time class DelphiDateTimeInvalidYear(delphi_date_time.DelphiDateTime): """Delphi TDateTime timestamp for testing invalid year.""" def _CopyDateTimeFromString(self, unused_time_string): """Copies a date and time from a string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Returns: dict[str, int]: date and time values, such as year, month, day of month, hours, minutes, seconds, microseconds. Raises: ValueError: if the time string is invalid or not supported. """ return { 'year': 10000, 'month': 1, 'day_of_month': 2, 'hours': 0, 'minutes': 0, 'seconds': 0} class DelphiDateTimeTest(unittest.TestCase): """Tests for the Delphi TDateTime timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" delphi_date_time_object = delphi_date_time.DelphiDateTime() expected_timestamp = 41443.0 delphi_date_time_object.CopyFromDateTimeString('2013-06-18') self.assertEqual(delphi_date_time_object.timestamp, expected_timestamp) expected_timestamp = 41443.82638888889 delphi_date_time_object.CopyFromDateTimeString('2013-06-18 19:50:00') self.assertEqual(delphi_date_time_object.timestamp, expected_timestamp) expected_timestamp = 41443.826395218464 delphi_date_time_object.CopyFromDateTimeString('2013-06-18 19:50:00.546875') self.assertEqual(delphi_date_time_object.timestamp, expected_timestamp) expected_timestamp = 41443.86806188513 delphi_date_time_object.CopyFromDateTimeString( '2013-06-18 19:50:00.546875-01:00') self.assertEqual(delphi_date_time_object.timestamp, expected_timestamp) expected_timestamp = 41443.78472855179 delphi_date_time_object.CopyFromDateTimeString( '2013-06-18 19:50:00.546875+01:00') self.assertEqual(delphi_date_time_object.timestamp, expected_timestamp) expected_timestamp = 1.0 delphi_date_time_object.CopyFromDateTimeString('1899-12-31 00:00:00') self.assertEqual(delphi_date_time_object.timestamp, expected_timestamp) delphi_date_time_object = DelphiDateTimeInvalidYear() with self.assertRaises(ValueError): delphi_date_time_object.CopyFromDateTimeString('9999-01-02 00:00:00') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" delphi_date_time_object = delphi_date_time.DelphiDateTime( timestamp=41443.8263953) expected_stat_time_tuple = (1371585000, 5539197) stat_time_tuple = delphi_date_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) delphi_date_time_object = delphi_date_time.DelphiDateTime() expected_stat_time_tuple = (None, None) stat_time_tuple = delphi_date_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" delphi_date_time_object = delphi_date_time.DelphiDateTime( timestamp=41443.8263953) date_time_string = delphi_date_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2013-06-18 19:50:00.553919') delphi_date_time_object = delphi_date_time.DelphiDateTime() date_time_string = delphi_date_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" delphi_date_time_object = delphi_date_time.DelphiDateTime( timestamp=41443.8263953) expected_micro_posix_timestamp = 1371585000553920 micro_posix_timestamp = delphi_date_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) delphi_date_time_object = delphi_date_time.DelphiDateTime() micro_posix_timestamp = delphi_date_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/fake_time.py000066400000000000000000000107311322532640600175230ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the fake time implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import fake_time class FakeTimeTest(unittest.TestCase): """Tests for the fake time.""" # pylint: disable=protected-access def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" fake_time_object = fake_time.FakeTime() expected_number_of_seconds = 1281571200 fake_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( fake_time_object._number_of_seconds, expected_number_of_seconds) self.assertIsNone(fake_time_object._microseconds) expected_number_of_seconds = 1281647191 fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( fake_time_object._number_of_seconds, expected_number_of_seconds) self.assertIsNone(fake_time_object._microseconds) expected_number_of_seconds = 1281647191 fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual( fake_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(fake_time_object._microseconds, 546875) expected_number_of_seconds = 1281650791 fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875-01:00') self.assertEqual( fake_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(fake_time_object._microseconds, 546875) expected_number_of_seconds = 1281643591 fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875+01:00') self.assertEqual( fake_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(fake_time_object._microseconds, 546875) expected_number_of_seconds = -11644387200 fake_time_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual( fake_time_object._number_of_seconds, expected_number_of_seconds) self.assertIsNone(fake_time_object._microseconds) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" fake_time_object = fake_time.FakeTime() fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') expected_stat_time_tuple = (1281647191, 5468750) stat_time_tuple = fake_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) fake_time_object = fake_time.FakeTime() fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') expected_stat_time_tuple = (1281647191, None) stat_time_tuple = fake_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) fake_time_object = fake_time.FakeTime() fake_time_object._number_of_seconds = None expected_stat_time_tuple = (None, None) stat_time_tuple = fake_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" fake_time_object = fake_time.FakeTime() fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') date_time_string = fake_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 21:06:31.546875') fake_time_object = fake_time.FakeTime() fake_time_object._number_of_seconds = None date_time_string = fake_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" fake_time_object = fake_time.FakeTime() fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') expected_micro_posix_number_of_seconds = 1281647191546875 micro_posix_number_of_seconds = fake_time_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) fake_time_object = fake_time.FakeTime() fake_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') expected_micro_posix_number_of_seconds = 1281647191000000 micro_posix_number_of_seconds = fake_time_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) fake_time_object = fake_time.FakeTime() fake_time_object._number_of_seconds = None micro_posix_number_of_seconds = fake_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_number_of_seconds) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/fat_date_time.py000066400000000000000000000112251322532640600203630ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the FAT date time implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import fat_date_time class FATDateTime(unittest.TestCase): """Tests for the FAT date time.""" # pylint: disable=protected-access def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" fat_date_time_object = fat_date_time.FATDateTime() expected_number_of_seconds = 966038400 fat_date_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( fat_date_time_object._number_of_seconds, expected_number_of_seconds) expected_number_of_seconds = 966114391 fat_date_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( fat_date_time_object._number_of_seconds, expected_number_of_seconds) expected_number_of_seconds = 966114391 fat_date_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual( fat_date_time_object._number_of_seconds, expected_number_of_seconds) expected_number_of_seconds = 966117991 fat_date_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual( fat_date_time_object._number_of_seconds, expected_number_of_seconds) expected_number_of_seconds = 966110791 fat_date_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual( fat_date_time_object._number_of_seconds, expected_number_of_seconds) expected_number_of_seconds = 86400 fat_date_time_object.CopyFromDateTimeString('1980-01-02 00:00:00') self.assertEqual( fat_date_time_object._number_of_seconds, expected_number_of_seconds) with self.assertRaises(ValueError): fat_date_time_object.CopyFromDateTimeString('2200-01-02 00:00:00') def testGetNumberOfSeconds(self): """Tests the _GetNumberOfSeconds function.""" fat_date_time_object = fat_date_time.FATDateTime() fat_date_time_object._GetNumberOfSeconds(0xa8d03d0c) # Invalid number of seconds. test_fat_date_time = (0xa8d03d0c & ~(0x1f << 16)) | ((30 & 0x1f) << 16) with self.assertRaises(ValueError): fat_date_time_object._GetNumberOfSeconds(test_fat_date_time) # Invalid number of minutes. test_fat_date_time = (0xa8d03d0c & ~(0x3f << 21)) | ((60 & 0x3f) << 21) with self.assertRaises(ValueError): fat_date_time_object._GetNumberOfSeconds(test_fat_date_time) # Invalid number of hours. test_fat_date_time = (0xa8d03d0c & ~(0x1f << 27)) | ((24 & 0x1f) << 27) with self.assertRaises(ValueError): fat_date_time_object._GetNumberOfSeconds(test_fat_date_time) # Invalid day of month. test_fat_date_time = (0xa8d03d0c & ~0x1f) | (32 & 0x1f) with self.assertRaises(ValueError): fat_date_time_object._GetNumberOfSeconds(test_fat_date_time) # Invalid month. test_fat_date_time = (0xa8d03d0c & ~(0x0f << 5)) | ((13 & 0x0f) << 5) with self.assertRaises(ValueError): fat_date_time_object._GetNumberOfSeconds(test_fat_date_time) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" fat_date_time_object = fat_date_time.FATDateTime(fat_date_time=0xa8d03d0c) expected_stat_time_tuple = (1281647192, None) stat_time_tuple = fat_date_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) fat_date_time_object = fat_date_time.FATDateTime() expected_stat_time_tuple = (None, None) stat_time_tuple = fat_date_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" fat_date_time_object = fat_date_time.FATDateTime(fat_date_time=0xa8d03d0c) date_time_string = fat_date_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 21:06:32') fat_date_time_object = fat_date_time.FATDateTime() date_time_string = fat_date_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" fat_date_time_object = fat_date_time.FATDateTime(fat_date_time=0xa8d03d0c) expected_micro_posix_timestamp = 1281647192000000 micro_posix_timestamp = fat_date_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) fat_date_time_object = fat_date_time.FATDateTime() micro_posix_timestamp = fat_date_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/filetime.py000066400000000000000000000067571322532640600174120ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the FILETIME timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import filetime class FiletimeTest(unittest.TestCase): """Tests for the FILETIME timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" filetime_object = filetime.Filetime() expected_timestamp = 0x1cb39b14e8c4000 filetime_object.CopyFromDateTimeString('2010-08-12') self.assertEqual(filetime_object.timestamp, expected_timestamp) expected_timestamp = 0x1cb3a623cb6a580 filetime_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual(filetime_object.timestamp, expected_timestamp) expected_timestamp = 0x01cb3a623d0a17ce filetime_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual(filetime_object.timestamp, expected_timestamp) expected_timestamp = 0x1cb3a6a9ece7fce filetime_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875-01:00') self.assertEqual(filetime_object.timestamp, expected_timestamp) expected_timestamp = 0x1cb3a59db45afce filetime_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875+01:00') self.assertEqual(filetime_object.timestamp, expected_timestamp) expected_timestamp = 86400 * 10000000 filetime_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual(filetime_object.timestamp, expected_timestamp) with self.assertRaises(ValueError): filetime_object.CopyFromDateTimeString('1500-01-02 00:00:00') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" filetime_object = filetime.Filetime(timestamp=0x01cb3a623d0a17ce) expected_stat_time_tuple = (1281647191, 5468750) stat_time_tuple = filetime_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) filetime_object = filetime.Filetime(timestamp=0x1ffffffffffffffff) expected_stat_time_tuple = (None, None) stat_time_tuple = filetime_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) filetime_object = filetime.Filetime() expected_stat_time_tuple = (None, None) stat_time_tuple = filetime_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" filetime_object = filetime.Filetime(timestamp=0x01cb3a623d0a17ce) date_time_string = filetime_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 21:06:31.5468750') filetime_object = filetime.Filetime() date_time_string = filetime_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" filetime_object = filetime.Filetime(timestamp=0x01cb3a623d0a17ce) expected_micro_posix_timestamp = 1281647191546875 micro_posix_timestamp = filetime_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) filetime_object = filetime.Filetime(timestamp=0x1ffffffffffffffff) micro_posix_timestamp = filetime_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) filetime_object = filetime.Filetime() micro_posix_timestamp = filetime_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/hfs_time.py000066400000000000000000000074151322532640600174020ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the HFS timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import hfs_time class HFSTimeTest(unittest.TestCase): """Tests for the HFS timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" hfs_time_object = hfs_time.HFSTime() expected_timestamp = 3458160000 hfs_time_object.CopyFromDateTimeString('2013-08-01') self.assertEqual(hfs_time_object.timestamp, expected_timestamp) expected_timestamp = 3458215528 hfs_time_object.CopyFromDateTimeString('2013-08-01 15:25:28') self.assertEqual(hfs_time_object.timestamp, expected_timestamp) expected_timestamp = 3458215528 hfs_time_object.CopyFromDateTimeString('2013-08-01 15:25:28.546875') self.assertEqual(hfs_time_object.timestamp, expected_timestamp) expected_timestamp = 3458219128 hfs_time_object.CopyFromDateTimeString('2013-08-01 15:25:28.546875-01:00') self.assertEqual(hfs_time_object.timestamp, expected_timestamp) expected_timestamp = 3458211928 hfs_time_object.CopyFromDateTimeString('2013-08-01 15:25:28.546875+01:00') self.assertEqual(hfs_time_object.timestamp, expected_timestamp) expected_timestamp = 86400 hfs_time_object.CopyFromDateTimeString('1904-01-02 00:00:00') self.assertEqual(hfs_time_object.timestamp, expected_timestamp) with self.assertRaises(ValueError): hfs_time_object.CopyFromDateTimeString('1600-01-02 00:00:00') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" hfs_time_object = hfs_time.HFSTime(timestamp=3458215528) expected_stat_time_tuple = (1375370728, 0) stat_time_tuple = hfs_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) hfs_time_object = hfs_time.HFSTime(timestamp=0x1ffffffff) expected_stat_time_tuple = (None, None) stat_time_tuple = hfs_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) hfs_time_object = hfs_time.HFSTime(timestamp=-0x1ffffffff) expected_stat_time_tuple = (None, None) stat_time_tuple = hfs_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) hfs_time_object = hfs_time.HFSTime() expected_stat_time_tuple = (None, None) stat_time_tuple = hfs_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" hfs_time_object = hfs_time.HFSTime(timestamp=3458215528) date_time_string = hfs_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2013-08-01 15:25:28') hfs_time_object = hfs_time.HFSTime() date_time_string = hfs_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" hfs_time_object = hfs_time.HFSTime(timestamp=3458215528) expected_micro_posix_timestamp = 1375370728000000 micro_posix_timestamp = hfs_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) hfs_time_object = hfs_time.HFSTime(timestamp=0x1ffffffff) micro_posix_timestamp = hfs_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) hfs_time_object = hfs_time.HFSTime(timestamp=-0x1ffffffff) micro_posix_timestamp = hfs_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) hfs_time_object = hfs_time.HFSTime() micro_posix_timestamp = hfs_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/interface.py000066400000000000000000000436631322532640600175510ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the date and time values interface.""" from __future__ import unicode_literals import unittest from dfdatetime import interface class DateTimeValuesTest(unittest.TestCase): """Tests for the date and time values interface.""" # pylint: disable=protected-access # TODO: add tests for _AdjustForTimeZoneOffset. def testCopyDateFromString(self): """Tests the _CopyDateFromString function.""" date_time_values = interface.DateTimeValues() expected_date_tuple = (2010, 1, 1) date_tuple = date_time_values._CopyDateFromString('2010-01-01') self.assertEqual(date_tuple, expected_date_tuple) expected_date_tuple = (2010, 8, 1) date_tuple = date_time_values._CopyDateFromString('2010-08-01') self.assertEqual(date_tuple, expected_date_tuple) expected_date_tuple = (2010, 8, 12) date_tuple = date_time_values._CopyDateFromString('2010-08-12') self.assertEqual(date_tuple, expected_date_tuple) expected_date_tuple = (2010, 8, 31) date_tuple = date_time_values._CopyDateFromString('2010-08-31') self.assertEqual(date_tuple, expected_date_tuple) expected_date_tuple = (2010, 12, 31) date_tuple = date_time_values._CopyDateFromString('2010-12-31') self.assertEqual(date_tuple, expected_date_tuple) expected_date_tuple = (1601, 1, 2) date_tuple = date_time_values._CopyDateFromString('1601-01-02') self.assertEqual(date_tuple, expected_date_tuple) with self.assertRaises(ValueError): date_time_values._CopyDateFromString('') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('195a-01-02') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('10000-01-02') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('2010-09-00') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('2010-09-31') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('1601-01-32') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('1601-01-b2') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('1601-13-02') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('1601-a1-02') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('2010-02-29') with self.assertRaises(ValueError): date_time_values._CopyDateFromString('2010-04-31') def testCopyDateTimeFromString(self): """Tests the _CopyDateTimeFromString function.""" date_time_values = interface.DateTimeValues() expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12} date_dict = date_time_values._CopyDateTimeFromString('2010-08-12') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 21, 'minutes': 6, 'seconds': 31} date_dict = date_time_values._CopyDateTimeFromString( '2010-08-12 21:06:31') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 21, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = date_time_values._CopyDateTimeFromString( '2010-08-12 21:06:31.546875') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 22, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = date_time_values._CopyDateTimeFromString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 20, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = date_time_values._CopyDateTimeFromString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 20, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = date_time_values._CopyDateTimeFromString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual(date_dict, expected_date_dict) # Test backwards date correction. expected_date_dict = { 'year': 2009, 'month': 12, 'day_of_month': 31, 'hours': 23, 'minutes': 45, 'seconds': 0, 'microseconds': 123456} date_dict = date_time_values._CopyDateTimeFromString( '2010-01-01 00:15:00.123456+00:30') self.assertEqual(date_dict, expected_date_dict) # Test forward date correction. expected_date_dict = { 'year': 2010, 'month': 1, 'day_of_month': 1, 'hours': 1, 'minutes': 15, 'seconds': 0, 'microseconds': 123456} date_dict = date_time_values._CopyDateTimeFromString( '2009-12-31 23:45:00.123456-01:30') self.assertEqual(date_dict, expected_date_dict) with self.assertRaises(ValueError): date_time_values._CopyDateTimeFromString('') with self.assertRaises(ValueError): date_time_values._CopyDateTimeFromString( '2010-08-12T21:06:31.546875+01:00') def testCopyTimeFromString(self): """Tests the _CopyTimeFromString function.""" date_time_values = interface.DateTimeValues() expected_time_tuple = (8, 4, 32, None, None) time_tuple = date_time_values._CopyTimeFromString('08:04:32') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, None, None) time_tuple = date_time_values._CopyTimeFromString('20:23:56') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, None, -330) time_tuple = date_time_values._CopyTimeFromString('20:23:56+05:30') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327000, None) time_tuple = date_time_values._CopyTimeFromString('20:23:56.327') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327000, -60) time_tuple = date_time_values._CopyTimeFromString('20:23:56.327+01:00') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327124, None) time_tuple = date_time_values._CopyTimeFromString('20:23:56.327124') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327124, 300) time_tuple = date_time_values._CopyTimeFromString('20:23:56.327124-05:00') self.assertEqual(time_tuple, expected_time_tuple) with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('14') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('14:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('24:00:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12b00:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00b00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('1s:00:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('00:60:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('00:e0:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('00:00:60') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('00:00:w0') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00.00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00.0000') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00.00w') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00+01b00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00+0w:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00+20:00') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00+01:0w') with self.assertRaises(ValueError): date_time_values._CopyTimeFromString('12:00:00+01:60') def testGetDateValues(self): """Tests the _GetDateValues function.""" date_time_values = interface.DateTimeValues() year, month, day_of_month = date_time_values._GetDateValues(0, 2000, 1, 1) self.assertEqual(year, 2000) self.assertEqual(month, 1) self.assertEqual(day_of_month, 1) year, month, day_of_month = date_time_values._GetDateValues(10, 2000, 1, 1) self.assertEqual(year, 2000) self.assertEqual(month, 1) self.assertEqual(day_of_month, 11) year, month, day_of_month = date_time_values._GetDateValues(100, 2000, 1, 1) self.assertEqual(year, 2000) self.assertEqual(month, 4) self.assertEqual(day_of_month, 10) year, month, day_of_month = date_time_values._GetDateValues(100, 1999, 1, 1) self.assertEqual(year, 1999) self.assertEqual(month, 4) self.assertEqual(day_of_month, 11) year, month, day_of_month = date_time_values._GetDateValues(0, 1999, 12, 30) self.assertEqual(year, 1999) self.assertEqual(month, 12) self.assertEqual(day_of_month, 30) year, month, day_of_month = date_time_values._GetDateValues(5, 1999, 12, 30) self.assertEqual(year, 2000) self.assertEqual(month, 1) self.assertEqual(day_of_month, 4) year, month, day_of_month = date_time_values._GetDateValues(-10, 2000, 1, 1) self.assertEqual(year, 1999) self.assertEqual(month, 12) self.assertEqual(day_of_month, 22) year, month, day_of_month = date_time_values._GetDateValues( -100, 2000, 1, 1) self.assertEqual(year, 1999) self.assertEqual(month, 9) self.assertEqual(day_of_month, 23) year, month, day_of_month = date_time_values._GetDateValues(-10, 2000, 1, 9) self.assertEqual(year, 1999) self.assertEqual(month, 12) self.assertEqual(day_of_month, 30) with self.assertRaises(ValueError): date_time_values._GetDateValues(10, -1, 1, 1) with self.assertRaises(ValueError): date_time_values._GetDateValues(10, 2000, 0, 1) with self.assertRaises(ValueError): date_time_values._GetDateValues(10, 2000, 13, 1) with self.assertRaises(ValueError): date_time_values._GetDateValues(10, 2000, 1, 0) with self.assertRaises(ValueError): date_time_values._GetDateValues(10, 2000, 1, 32) year, month, day_of_month = date_time_values._GetDateValues( 0, 1899, 12, 30) self.assertEqual(year, 1899) self.assertEqual(month, 12) self.assertEqual(day_of_month, 30) year, month, day_of_month = date_time_values._GetDateValues( 25569, 1899, 12, 30) self.assertEqual(year, 1970) self.assertEqual(month, 1) self.assertEqual(day_of_month, 1) year, month, day_of_month = date_time_values._GetDateValues( 36526, 1899, 12, 30) self.assertEqual(year, 2000) self.assertEqual(month, 1) self.assertEqual(day_of_month, 1) year, month, day_of_month = date_time_values._GetDateValues( 41275, 1899, 12, 30) self.assertEqual(year, 2013) self.assertEqual(month, 1) self.assertEqual(day_of_month, 1) year, month, day_of_month = date_time_values._GetDateValues( 41443, 1899, 12, 30) self.assertEqual(year, 2013) self.assertEqual(month, 6) self.assertEqual(day_of_month, 18) year, month, day_of_month = date_time_values._GetDateValues( -25569, 1899, 12, 30) self.assertEqual(year, 1829) self.assertEqual(month, 12) self.assertEqual(day_of_month, 28) def testGetDayOfYear(self): """Tests the _GetDayOfYear function.""" date_time_values = interface.DateTimeValues() day_of_year = date_time_values._GetDayOfYear(1999, 1, 1) self.assertEqual(day_of_year, 1) day_of_year = date_time_values._GetDayOfYear(1999, 4, 21) self.assertEqual(day_of_year, 111) day_of_year = date_time_values._GetDayOfYear(1999, 12, 31) self.assertEqual(day_of_year, 365) day_of_year = date_time_values._GetDayOfYear(2000, 1, 1) self.assertEqual(day_of_year, 1) day_of_year = date_time_values._GetDayOfYear(2000, 4, 21) self.assertEqual(day_of_year, 112) day_of_year = date_time_values._GetDayOfYear(2000, 12, 31) self.assertEqual(day_of_year, 366) with self.assertRaises(ValueError): date_time_values._GetDayOfYear(1999, 0, 1) with self.assertRaises(ValueError): date_time_values._GetDayOfYear(1999, 13, 1) with self.assertRaises(ValueError): date_time_values._GetDayOfYear(1999, 1, 0) with self.assertRaises(ValueError): date_time_values._GetDayOfYear(1999, 1, 32) def testGetDaysPerMonth(self): """Tests the _GetDaysPerMonth function.""" date_time_values = interface.DateTimeValues() expected_days_per_month = list(interface.DateTimeValues._DAYS_PER_MONTH) days_per_month = [] for month in range(1, 13): days_per_month.append(date_time_values._GetDaysPerMonth(1999, month)) self.assertEqual(days_per_month, expected_days_per_month) expected_days_per_month[1] += 1 days_per_month = [] for month in range(1, 13): days_per_month.append(date_time_values._GetDaysPerMonth(2000, month)) self.assertEqual(days_per_month, expected_days_per_month) with self.assertRaises(ValueError): date_time_values._GetDaysPerMonth(1999, 0) with self.assertRaises(ValueError): date_time_values._GetDaysPerMonth(1999, 13) def testGetNumberOfDaysInCentury(self): """Tests the _GetNumberOfDaysInCentury function.""" date_time_values = interface.DateTimeValues() self.assertEqual(date_time_values._GetNumberOfDaysInCentury(1700), 36524) self.assertEqual(date_time_values._GetNumberOfDaysInCentury(2000), 36525) with self.assertRaises(ValueError): date_time_values._GetNumberOfDaysInCentury(-1) def testGetNumberOfDaysInYear(self): """Tests the _GetNumberOfDaysInYear function.""" date_time_values = interface.DateTimeValues() self.assertEqual(date_time_values._GetNumberOfDaysInYear(1999), 365) self.assertEqual(date_time_values._GetNumberOfDaysInYear(2000), 366) self.assertEqual(date_time_values._GetNumberOfDaysInYear(1996), 366) def testGetNumberOfSecondsFromElements(self): """Tests the _GetNumberOfSecondsFromElements function.""" date_time_values = interface.DateTimeValues() number_of_seconds = date_time_values._GetNumberOfSecondsFromElements( 2010, 8, 12, 0, 0, 0) self.assertEqual(number_of_seconds, 1281571200) number_of_seconds = date_time_values._GetNumberOfSecondsFromElements( 2010, 8, 12, None, None, None) self.assertEqual(number_of_seconds, 1281571200) number_of_seconds = date_time_values._GetNumberOfSecondsFromElements( 2010, 8, 12, 21, 6, 31) self.assertEqual(number_of_seconds, 1281647191) number_of_seconds = date_time_values._GetNumberOfSecondsFromElements( 1601, 1, 2, 0, 0, 0) self.assertEqual(number_of_seconds, -11644387200) number_of_seconds = date_time_values._GetNumberOfSecondsFromElements( 0, 1, 2, 0, 0, 0) self.assertIsNone(number_of_seconds) with self.assertRaises(ValueError): date_time_values._GetNumberOfSecondsFromElements(2010, 13, 12, 21, 6, 31) with self.assertRaises(ValueError): date_time_values._GetNumberOfSecondsFromElements(2010, 13, 12, 24, 6, 31) with self.assertRaises(ValueError): date_time_values._GetNumberOfSecondsFromElements(2010, 13, 12, 21, 99, 31) with self.assertRaises(ValueError): date_time_values._GetNumberOfSecondsFromElements(2010, 13, 12, 21, 6, 65) with self.assertRaises(ValueError): date_time_values._GetNumberOfSecondsFromElements(2013, 2, 29, 1, 4, 25) def testGetTimeValues(self): """Tests the _GetTimeValues function.""" date_time_values = interface.DateTimeValues() days, hours, minutes, seconds = date_time_values._GetTimeValues(10) self.assertEqual(days, 0) self.assertEqual(hours, 0) self.assertEqual(minutes, 0) self.assertEqual(seconds, 10) days, hours, minutes, seconds = date_time_values._GetTimeValues(190) self.assertEqual(days, 0) self.assertEqual(hours, 0) self.assertEqual(minutes, 3) self.assertEqual(seconds, 10) days, hours, minutes, seconds = date_time_values._GetTimeValues(18190) self.assertEqual(days, 0) self.assertEqual(hours, 5) self.assertEqual(minutes, 3) self.assertEqual(seconds, 10) days, hours, minutes, seconds = date_time_values._GetTimeValues(190990) self.assertEqual(days, 2) self.assertEqual(hours, 5) self.assertEqual(minutes, 3) self.assertEqual(seconds, 10) days, hours, minutes, seconds = date_time_values._GetTimeValues(-10) self.assertEqual(days, -1) self.assertEqual(hours, 23) self.assertEqual(minutes, 59) self.assertEqual(seconds, 50) days, hours, minutes, seconds = date_time_values._GetTimeValues(-190) self.assertEqual(days, -1) self.assertEqual(hours, 23) self.assertEqual(minutes, 56) self.assertEqual(seconds, 50) days, hours, minutes, seconds = date_time_values._GetTimeValues(-18190) self.assertEqual(days, -1) self.assertEqual(hours, 18) self.assertEqual(minutes, 56) self.assertEqual(seconds, 50) days, hours, minutes, seconds = date_time_values._GetTimeValues(-190990) self.assertEqual(days, -3) self.assertEqual(hours, 18) self.assertEqual(minutes, 56) self.assertEqual(seconds, 50) def testIsLeapYear(self): """Tests the _IsLeapYear function.""" date_time_values = interface.DateTimeValues() self.assertFalse(date_time_values._IsLeapYear(1999)) self.assertTrue(date_time_values._IsLeapYear(2000)) self.assertTrue(date_time_values._IsLeapYear(1996)) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/java_time.py000066400000000000000000000057511322532640600175440ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the Java java.util.Date timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import java_time class JavaTimeTest(unittest.TestCase): """Tests for the Java java.util.Date timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" java_time_object = java_time.JavaTime() expected_timestamp = 1281571200000 java_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual(java_time_object.timestamp, expected_timestamp) expected_timestamp = 1281647191000 java_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual(java_time_object.timestamp, expected_timestamp) expected_timestamp = 1281647191546 java_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual(java_time_object.timestamp, expected_timestamp) expected_timestamp = 1281650791546 java_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875-01:00') self.assertEqual(java_time_object.timestamp, expected_timestamp) expected_timestamp = 1281643591546 java_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875+01:00') self.assertEqual(java_time_object.timestamp, expected_timestamp) expected_timestamp = -11644387200000 java_time_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual(java_time_object.timestamp, expected_timestamp) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" java_time_object = java_time.JavaTime(timestamp=1281643591546) expected_stat_time_tuple = (1281643591, 5460000) stat_time_tuple = java_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) java_time_object = java_time.JavaTime() expected_stat_time_tuple = (None, None) stat_time_tuple = java_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" java_time_object = java_time.JavaTime(timestamp=1281643591546) date_time_string = java_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31.546') java_time_object = java_time.JavaTime() date_time_string = java_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" java_time_object = java_time.JavaTime(timestamp=1281643591546) expected_micro_posix_timestamp = 1281643591546000 micro_posix_timestamp = java_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) java_time_object = java_time.JavaTime() micro_posix_timestamp = java_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/ole_automation_date.py000066400000000000000000000066341322532640600216220ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the OLE Automation date implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import ole_automation_date class OLEAutomationDateTest(unittest.TestCase): """Tests for the OLE Automation date.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" ole_automation_date_object = ole_automation_date.OLEAutomationDate() expected_timestamp = 43044.0 ole_automation_date_object.CopyFromDateTimeString('2017-11-05') self.assertEqual(ole_automation_date_object.timestamp, expected_timestamp) expected_timestamp = 43044.48055555555 ole_automation_date_object.CopyFromDateTimeString('2017-11-05 11:32:00') self.assertEqual(ole_automation_date_object.timestamp, expected_timestamp) expected_timestamp = 43044.480561885124 ole_automation_date_object.CopyFromDateTimeString( '2017-11-05 11:32:00.546875') self.assertEqual(ole_automation_date_object.timestamp, expected_timestamp) expected_timestamp = 43044.522228551796 ole_automation_date_object.CopyFromDateTimeString( '2017-11-05 11:32:00.546875-01:00') self.assertEqual(ole_automation_date_object.timestamp, expected_timestamp) expected_timestamp = 43044.43889521846 ole_automation_date_object.CopyFromDateTimeString( '2017-11-05 11:32:00.546875+01:00') self.assertEqual(ole_automation_date_object.timestamp, expected_timestamp) expected_timestamp = 2.0 ole_automation_date_object.CopyFromDateTimeString('1900-01-01 00:00:00') self.assertEqual(ole_automation_date_object.timestamp, expected_timestamp) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" ole_automation_date_object = ole_automation_date.OLEAutomationDate( timestamp=43044.480556) expected_stat_time_tuple = (1509881520, 384001) stat_time_tuple = ole_automation_date_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) ole_automation_date_object = ole_automation_date.OLEAutomationDate() expected_stat_time_tuple = (None, None) stat_time_tuple = ole_automation_date_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" ole_automation_date_object = ole_automation_date.OLEAutomationDate( timestamp=43044.480556) date_time_string = ole_automation_date_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2017-11-05 11:32:00.038400') ole_automation_date_object = ole_automation_date.OLEAutomationDate() date_time_string = ole_automation_date_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" ole_automation_date_object = ole_automation_date.OLEAutomationDate( timestamp=43044.480556) expected_micro_posix_timestamp = 1509881520038400 micro_posix_timestamp = ole_automation_date_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) ole_automation_date_object = ole_automation_date.OLEAutomationDate() micro_posix_timestamp = ole_automation_date_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/posix_time.py000066400000000000000000000136311322532640600177610ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the POSIX timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import posix_time class PosixTimeTest(unittest.TestCase): """Tests for the POSIX timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" posix_time_object = posix_time.PosixTime() expected_timestamp = 1281571200 posix_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281647191 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281647191 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281650791 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875-01:00') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281643591 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875+01:00') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = -11644387200 posix_time_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual(posix_time_object.timestamp, expected_timestamp) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" posix_time_object = posix_time.PosixTime(timestamp=1281643591) expected_stat_time_tuple = (1281643591, None) stat_time_tuple = posix_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) posix_time_object = posix_time.PosixTime() expected_stat_time_tuple = (None, None) stat_time_tuple = posix_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" posix_time_object = posix_time.PosixTime(timestamp=1281643591) date_time_string = posix_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31') posix_time_object = posix_time.PosixTime() date_time_string = posix_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" posix_time_object = posix_time.PosixTime(timestamp=1281643591) expected_micro_posix_timestamp = 1281643591000000 micro_posix_timestamp = posix_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) posix_time_object = posix_time.PosixTime() micro_posix_timestamp = posix_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) class PosixTimeInMicrosecondsTest(unittest.TestCase): """Tests for the POSIX timestamp in microseconds.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" posix_time_object = posix_time.PosixTimeInMicroseconds() expected_timestamp = 1281571200000000 posix_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281647191000000 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281647191546875 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281650791546875 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875-01:00') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = 1281643591546875 posix_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875+01:00') self.assertEqual(posix_time_object.timestamp, expected_timestamp) expected_timestamp = -11644387200000000 posix_time_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual(posix_time_object.timestamp, expected_timestamp) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" posix_time_object = posix_time.PosixTimeInMicroseconds( timestamp=1281643591546875) expected_stat_time_tuple = (1281643591, 5468750) stat_time_tuple = posix_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) posix_time_object = posix_time.PosixTimeInMicroseconds() expected_stat_time_tuple = (None, None) stat_time_tuple = posix_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" posix_time_object = posix_time.PosixTimeInMicroseconds( timestamp=1281643591546875) date_time_string = posix_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31.546875') posix_time_object = posix_time.PosixTimeInMicroseconds() date_time_string = posix_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" posix_time_object = posix_time.PosixTimeInMicroseconds( timestamp=1281643591546875) expected_micro_posix_timestamp = 1281643591546875 micro_posix_timestamp = posix_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) posix_time_object = posix_time.PosixTimeInMicroseconds() micro_posix_timestamp = posix_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/precisions.py000066400000000000000000000111171322532640600177540ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for date and time precision helpers.""" from __future__ import unicode_literals import unittest from dfdatetime import definitions from dfdatetime import precisions class DateTimePrecisionHelperTest(unittest.TestCase): """Tests for the date time precision helper interface.""" def testCopyMicrosecondsToFractionOfSecond(self): """Tests the CopyMicrosecondsToFractionOfSecond function.""" precision_helper = precisions.DateTimePrecisionHelper with self.assertRaises(NotImplementedError): precision_helper.CopyMicrosecondsToFractionOfSecond(0) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" precision_helper = precisions.DateTimePrecisionHelper with self.assertRaises(NotImplementedError): precision_helper.CopyToDateTimeString((2018, 1, 2, 19, 45, 12), 0.5) class SecondsPrecisionHelperTest(unittest.TestCase): """Tests for the seconds precision helper.""" def testCopyMicrosecondsToFractionOfSecond(self): """Tests the CopyMicrosecondsToFractionOfSecond function.""" precision_helper = precisions.SecondsPrecisionHelper fraction_of_second = precision_helper.CopyMicrosecondsToFractionOfSecond( 123456) self.assertEqual(fraction_of_second, 0.0) with self.assertRaises(ValueError): precision_helper.CopyMicrosecondsToFractionOfSecond(-1) with self.assertRaises(ValueError): precision_helper.CopyMicrosecondsToFractionOfSecond(1000000) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" precision_helper = precisions.SecondsPrecisionHelper date_time_string = precision_helper.CopyToDateTimeString( (2018, 1, 2, 19, 45, 12), 0.123456) self.assertEqual(date_time_string, '2018-01-02 19:45:12') with self.assertRaises(ValueError): precision_helper.CopyToDateTimeString((2018, 1, 2, 19, 45, 12), 4.123456) class MillisecondsPrecisionHelperTest(unittest.TestCase): """Tests for the milliseconds precision helper.""" def testCopyMicrosecondsToFractionOfSecond(self): """Tests the CopyMicrosecondsToFractionOfSecond function.""" precision_helper = precisions.MillisecondsPrecisionHelper fraction_of_second = precision_helper.CopyMicrosecondsToFractionOfSecond( 123456) self.assertEqual(fraction_of_second, 0.123) with self.assertRaises(ValueError): precision_helper.CopyMicrosecondsToFractionOfSecond(-1) with self.assertRaises(ValueError): precision_helper.CopyMicrosecondsToFractionOfSecond(1000000) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" precision_helper = precisions.MillisecondsPrecisionHelper date_time_string = precision_helper.CopyToDateTimeString( (2018, 1, 2, 19, 45, 12), 0.123456) self.assertEqual(date_time_string, '2018-01-02 19:45:12.123') with self.assertRaises(ValueError): precision_helper.CopyToDateTimeString((2018, 1, 2, 19, 45, 12), 4.123456) class MicrosecondsPrecisionHelperTest(unittest.TestCase): """Tests for the milliseconds precision helper.""" def testCopyMicrosecondsToFractionOfSecond(self): """Tests the CopyMicrosecondsToFractionOfSecond function.""" precision_helper = precisions.MicrosecondsPrecisionHelper fraction_of_second = precision_helper.CopyMicrosecondsToFractionOfSecond( 123456) self.assertEqual(fraction_of_second, 0.123456) with self.assertRaises(ValueError): precision_helper.CopyMicrosecondsToFractionOfSecond(-1) with self.assertRaises(ValueError): precision_helper.CopyMicrosecondsToFractionOfSecond(1000000) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" precision_helper = precisions.MicrosecondsPrecisionHelper date_time_string = precision_helper.CopyToDateTimeString( (2018, 1, 2, 19, 45, 12), 0.123456) self.assertEqual(date_time_string, '2018-01-02 19:45:12.123456') with self.assertRaises(ValueError): precision_helper.CopyToDateTimeString((2018, 1, 2, 19, 45, 12), 4.123456) class PrecisionHelperFactoryTest(unittest.TestCase): """Tests for the date time precision helper factory.""" def testCreatePrecisionHelper(self): """Tests the CreatePrecisionHelper function.""" precision_helper = precisions.PrecisionHelperFactory.CreatePrecisionHelper( definitions.PRECISION_1_MICROSECOND) self.assertIsNotNone(precision_helper) with self.assertRaises(ValueError): precisions.PrecisionHelperFactory.CreatePrecisionHelper('bogus') if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/rfc2579_date_time.py000066400000000000000000000232741322532640600207210ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the RFC2579 date-time implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import rfc2579_date_time class RFC2579DateTimeInvalidYear(rfc2579_date_time.RFC2579DateTime): """RFC2579 date-time for testing invalid year.""" def _CopyDateTimeFromString(self, unused_time_string): """Copies a date and time from a string. Args: time_string (str): date and time value formatted as: YYYY-MM-DD hh:mm:ss.######[+-]##:## Where # are numeric digits ranging from 0 to 9 and the seconds fraction can be either 3 or 6 digits. The time of day, seconds fraction and time zone offset are optional. The default time zone is UTC. Returns: dict[str, int]: date and time values, such as year, month, day of month, hours, minutes, seconds, microseconds. Raises: ValueError: if the time string is invalid or not supported. """ return { 'year': 70000, 'month': 1, 'day_of_month': 2, 'hours': 0, 'minutes': 0, 'seconds': 0} class RFC2579DateTimeTest(unittest.TestCase): """Tests for the RFC2579 date-time.""" # pylint: disable=protected-access def testInitialize(self): """Tests the initialization function.""" rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime() self.assertIsNotNone(rfc2579_date_time_object) rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '+', 2, 0)) self.assertIsNotNone(rfc2579_date_time_object) self.assertEqual(rfc2579_date_time_object.year, 2010) self.assertEqual(rfc2579_date_time_object.month, 8) self.assertEqual(rfc2579_date_time_object.day_of_month, 12) self.assertEqual(rfc2579_date_time_object.hours, 18) self.assertEqual(rfc2579_date_time_object.minutes, 6) self.assertEqual(rfc2579_date_time_object.seconds, 31) self.assertEqual(rfc2579_date_time_object.deciseconds, 6) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(65537, 8, 12, 20, 6, 31, 6, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 13, 12, 20, 6, 31, 6, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 32, 20, 6, 31, 6, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 24, 6, 31, 6, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 61, 31, 6, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 61, 6, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 11, '+', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '#', 2, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '+', 14, 0)) with self.assertRaises(ValueError): rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '+', 2, 60)) def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime() expected_number_of_seconds = 1281571200 rfc2579_date_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( rfc2579_date_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(rfc2579_date_time_object.year, 2010) self.assertEqual(rfc2579_date_time_object.month, 8) self.assertEqual(rfc2579_date_time_object.day_of_month, 12) self.assertEqual(rfc2579_date_time_object.hours, 0) self.assertEqual(rfc2579_date_time_object.minutes, 0) self.assertEqual(rfc2579_date_time_object.seconds, 0) self.assertEqual(rfc2579_date_time_object.deciseconds, 0) expected_number_of_seconds = 1281647191 rfc2579_date_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( rfc2579_date_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(rfc2579_date_time_object.year, 2010) self.assertEqual(rfc2579_date_time_object.month, 8) self.assertEqual(rfc2579_date_time_object.day_of_month, 12) self.assertEqual(rfc2579_date_time_object.hours, 21) self.assertEqual(rfc2579_date_time_object.minutes, 6) self.assertEqual(rfc2579_date_time_object.seconds, 31) self.assertEqual(rfc2579_date_time_object.deciseconds, 0) expected_number_of_seconds = 1281647191 rfc2579_date_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875') self.assertEqual( rfc2579_date_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(rfc2579_date_time_object.year, 2010) self.assertEqual(rfc2579_date_time_object.month, 8) self.assertEqual(rfc2579_date_time_object.day_of_month, 12) self.assertEqual(rfc2579_date_time_object.hours, 21) self.assertEqual(rfc2579_date_time_object.minutes, 6) self.assertEqual(rfc2579_date_time_object.seconds, 31) self.assertEqual(rfc2579_date_time_object.deciseconds, 5) expected_number_of_seconds = 1281650791 rfc2579_date_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual( rfc2579_date_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(rfc2579_date_time_object.year, 2010) self.assertEqual(rfc2579_date_time_object.month, 8) self.assertEqual(rfc2579_date_time_object.day_of_month, 12) self.assertEqual(rfc2579_date_time_object.hours, 22) self.assertEqual(rfc2579_date_time_object.minutes, 6) self.assertEqual(rfc2579_date_time_object.seconds, 31) self.assertEqual(rfc2579_date_time_object.deciseconds, 5) expected_number_of_seconds = 1281643591 rfc2579_date_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual( rfc2579_date_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(rfc2579_date_time_object.year, 2010) self.assertEqual(rfc2579_date_time_object.month, 8) self.assertEqual(rfc2579_date_time_object.day_of_month, 12) self.assertEqual(rfc2579_date_time_object.hours, 20) self.assertEqual(rfc2579_date_time_object.minutes, 6) self.assertEqual(rfc2579_date_time_object.seconds, 31) self.assertEqual(rfc2579_date_time_object.deciseconds, 5) expected_number_of_seconds = -11644387200 rfc2579_date_time_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual( rfc2579_date_time_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(rfc2579_date_time_object.year, 1601) self.assertEqual(rfc2579_date_time_object.month, 1) self.assertEqual(rfc2579_date_time_object.day_of_month, 2) self.assertEqual(rfc2579_date_time_object.hours, 0) self.assertEqual(rfc2579_date_time_object.minutes, 0) self.assertEqual(rfc2579_date_time_object.seconds, 0) self.assertEqual(rfc2579_date_time_object.deciseconds, 0) rfc2579_date_time_object = RFC2579DateTimeInvalidYear() with self.assertRaises(ValueError): rfc2579_date_time_object.CopyFromDateTimeString('9999-01-02 00:00:00') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '+', 0, 0)) expected_stat_time_tuple = (1281643591, 6000000) stat_time_tuple = rfc2579_date_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime() expected_stat_time_tuple = (None, None) stat_time_tuple = rfc2579_date_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '+', 0, 0)) date_time_string = rfc2579_date_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31.6') rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime() date_time_string = rfc2579_date_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime( rfc2579_date_time_tuple=(2010, 8, 12, 20, 6, 31, 6, '+', 0, 0)) expected_micro_posix_number_of_seconds = 1281643591600000 micro_posix_number_of_seconds = rfc2579_date_time_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) rfc2579_date_time_object = rfc2579_date_time.RFC2579DateTime() micro_posix_number_of_seconds = rfc2579_date_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_number_of_seconds) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/semantic_time.py000066400000000000000000000044711322532640600204240ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the semantic time implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import semantic_time class SemanticTimeTest(unittest.TestCase): """Tests for semantic time.""" # pylint: disable=protected-access def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" semantic_time_object = semantic_time.SemanticTime() semantic_time_object.CopyFromDateTimeString('Never') self.assertEqual(semantic_time_object.string, 'Never') def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" semantic_time_object = semantic_time.SemanticTime(string='Never') date_time_string = semantic_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, 'Never') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" semantic_time_object = semantic_time.SemanticTime() expected_stat_time_tuple = (0, 0) stat_time_tuple = semantic_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" semantic_time_object = semantic_time.SemanticTime() expected_micro_posix_timestamp = 0 micro_posix_timestamp = semantic_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) class InvalidTimeTest(unittest.TestCase): """Tests for semantic time that represents invalid..""" def testInitialize(self): """Tests the __init__ function.""" semantic_time_object = semantic_time.InvalidTime() self.assertEqual(semantic_time_object.string, 'Invalid') class NeverTest(unittest.TestCase): """Tests for semantic time that represents never.""" def testInitialize(self): """Tests the __init__ function.""" semantic_time_object = semantic_time.Never() self.assertEqual(semantic_time_object.string, 'Never') class NotSetTest(unittest.TestCase): """Tests for semantic time that represents not set.""" def testInitialize(self): """Tests the __init__ function.""" semantic_time_object = semantic_time.NotSet() self.assertEqual(semantic_time_object.string, 'Not set') if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/systemtime.py000066400000000000000000000167371322532640600200160ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the SYSTEMTIME structure implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import systemtime class FiletimeTest(unittest.TestCase): """Tests for the SYSTEMTIME structure.""" # pylint: disable=protected-access def testInitialize(self): """Tests the initialization function.""" systemtime_object = systemtime.Systemtime() self.assertIsNotNone(systemtime_object) systemtime_object = systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 31, 142)) self.assertIsNotNone(systemtime_object) self.assertEqual(systemtime_object.year, 2010) self.assertEqual(systemtime_object.month, 8) self.assertEqual(systemtime_object.day_of_month, 12) self.assertEqual(systemtime_object.hours, 20) self.assertEqual(systemtime_object.minutes, 6) self.assertEqual(systemtime_object.seconds, 31) self.assertEqual(systemtime_object.milliseconds, 142) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 31)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(1500, 8, 4, 12, 20, 6, 31, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 13, 4, 12, 20, 6, 31, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 7, 12, 20, 6, 31, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 32, 20, 6, 31, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 24, 6, 31, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 61, 31, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 61, 142)) with self.assertRaises(ValueError): systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 31, 1001)) def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" systemtime_object = systemtime.Systemtime() expected_number_of_seconds = 1281571200 systemtime_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( systemtime_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(systemtime_object.year, 2010) self.assertEqual(systemtime_object.month, 8) self.assertEqual(systemtime_object.day_of_month, 12) self.assertEqual(systemtime_object.hours, 0) self.assertEqual(systemtime_object.minutes, 0) self.assertEqual(systemtime_object.seconds, 0) self.assertEqual(systemtime_object.milliseconds, 0) expected_number_of_seconds = 1281647191 systemtime_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( systemtime_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(systemtime_object.year, 2010) self.assertEqual(systemtime_object.month, 8) self.assertEqual(systemtime_object.day_of_month, 12) self.assertEqual(systemtime_object.hours, 21) self.assertEqual(systemtime_object.minutes, 6) self.assertEqual(systemtime_object.seconds, 31) self.assertEqual(systemtime_object.milliseconds, 0) expected_number_of_seconds = 1281647191 systemtime_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual( systemtime_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(systemtime_object.year, 2010) self.assertEqual(systemtime_object.month, 8) self.assertEqual(systemtime_object.day_of_month, 12) self.assertEqual(systemtime_object.hours, 21) self.assertEqual(systemtime_object.minutes, 6) self.assertEqual(systemtime_object.seconds, 31) self.assertEqual(systemtime_object.milliseconds, 546) expected_number_of_seconds = 1281650791 systemtime_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875-01:00') self.assertEqual( systemtime_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(systemtime_object.year, 2010) self.assertEqual(systemtime_object.month, 8) self.assertEqual(systemtime_object.day_of_month, 12) self.assertEqual(systemtime_object.hours, 22) self.assertEqual(systemtime_object.minutes, 6) self.assertEqual(systemtime_object.seconds, 31) self.assertEqual(systemtime_object.milliseconds, 546) expected_number_of_seconds = 1281643591 systemtime_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875+01:00') self.assertEqual( systemtime_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(systemtime_object.year, 2010) self.assertEqual(systemtime_object.month, 8) self.assertEqual(systemtime_object.day_of_month, 12) self.assertEqual(systemtime_object.hours, 20) self.assertEqual(systemtime_object.minutes, 6) self.assertEqual(systemtime_object.seconds, 31) self.assertEqual(systemtime_object.milliseconds, 546) expected_number_of_seconds = -11644387200 systemtime_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual( systemtime_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(systemtime_object.year, 1601) self.assertEqual(systemtime_object.month, 1) self.assertEqual(systemtime_object.day_of_month, 2) self.assertEqual(systemtime_object.hours, 0) self.assertEqual(systemtime_object.minutes, 0) self.assertEqual(systemtime_object.seconds, 0) self.assertEqual(systemtime_object.milliseconds, 0) with self.assertRaises(ValueError): systemtime_object.CopyFromDateTimeString('1600-01-02 00:00:00') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" systemtime_object = systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 31, 142)) expected_stat_time_tuple = (1281643591, 1420000) stat_time_tuple = systemtime_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) systemtime_object = systemtime.Systemtime() expected_stat_time_tuple = (None, None) stat_time_tuple = systemtime_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" systemtime_object = systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 31, 142)) date_time_string = systemtime_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31.142') systemtime_object = systemtime.Systemtime() date_time_string = systemtime_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" systemtime_object = systemtime.Systemtime( system_time_tuple=(2010, 8, 4, 12, 20, 6, 31, 142)) expected_micro_posix_number_of_seconds = 1281643591142000 micro_posix_number_of_seconds = systemtime_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) systemtime_object = systemtime.Systemtime() micro_posix_number_of_seconds = systemtime_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_number_of_seconds) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/time_elements.py000066400000000000000000001231001322532640600204240ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the time elements implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import time_elements class TimeElementsTest(unittest.TestCase): """Tests for the time elements.""" # pylint: disable=protected-access def testInitialize(self): """Tests the initialization function.""" time_elements_object = time_elements.TimeElements() self.assertIsNotNone(time_elements_object) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) time_elements_object = time_elements.TimeElements( time_elements_tuple=(2010, 8, 12, 20, 6, 31)) self.assertIsNotNone(time_elements_object) self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) with self.assertRaises(ValueError): time_elements.TimeElements( time_elements_tuple=(2010, 8, 12, 20, 6)) with self.assertRaises(ValueError): time_elements.TimeElements( time_elements_tuple=(2010, 13, 12, 20, 6, 31)) def testCopyDateTimeFromStringISO8601(self): """Tests the _CopyDateTimeFromStringISO8601 function.""" time_elements_object = time_elements.TimeElements() expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 21, 'minutes': 6, 'seconds': 31} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12T21:06:31') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 21, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12T21:06:31.546875') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 22, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12T21:06:31.546875-01:00') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 20, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12T21:06:31.546875+01:00') self.assertEqual(date_dict, expected_date_dict) expected_date_dict = { 'year': 2010, 'month': 8, 'day_of_month': 12, 'hours': 20, 'minutes': 6, 'seconds': 31, 'microseconds': 546875} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12T21:06:31.546875+01:00') self.assertEqual(date_dict, expected_date_dict) # Test backwards date correction. expected_date_dict = { 'year': 2009, 'month': 12, 'day_of_month': 31, 'hours': 23, 'minutes': 45, 'seconds': 0, 'microseconds': 123456} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2010-01-01T00:15:00.123456+00:30') self.assertEqual(date_dict, expected_date_dict) # Test forward date correction. expected_date_dict = { 'year': 2010, 'month': 1, 'day_of_month': 1, 'hours': 1, 'minutes': 15, 'seconds': 0, 'microseconds': 123456} date_dict = time_elements_object._CopyDateTimeFromStringISO8601( '2009-12-31T23:45:00.123456-01:30') self.assertEqual(date_dict, expected_date_dict) with self.assertRaises(ValueError): time_elements_object._CopyDateTimeFromStringISO8601('') with self.assertRaises(ValueError): time_elements_object._CopyDateTimeFromStringISO8601('2010-08-12T1') with self.assertRaises(ValueError): time_elements_object._CopyDateTimeFromStringISO8601( '2010-08-12 21:06:31.546875+01:00') # TODO: add tests for _CopyFromDateTimeValues def testCopyTimeFromStringISO8601(self): """Tests the _CopyTimeFromStringISO8601 function.""" time_elements_object = time_elements.TimeElements() expected_time_tuple = (8, None, None, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('08') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (8, 4, None, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('08:04') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (8, 4, None, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('0804') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 30, 0, 0, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('20.5') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (8, 4, 32, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('08:04:32') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (8, 4, 32, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('080432') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 30, 0, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('20:23.5') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 30, 0, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('2023.5') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (8, 4, 32, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('08:04:32Z') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, None, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('20:23:56') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, None, -330) time_tuple = time_elements_object._CopyTimeFromStringISO8601( '20:23:56+05:30') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327000, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601('20:23:56.327') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327000, -60) time_tuple = time_elements_object._CopyTimeFromStringISO8601( '20:23:56.327+01:00') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327124, None) time_tuple = time_elements_object._CopyTimeFromStringISO8601( '20:23:56.327124') self.assertEqual(time_tuple, expected_time_tuple) expected_time_tuple = (20, 23, 56, 327124, 300) time_tuple = time_elements_object._CopyTimeFromStringISO8601( '20:23:56.327124-05:00') self.assertEqual(time_tuple, expected_time_tuple) with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('1') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('14:1') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('14:15:1') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('24:00:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12b00:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00b00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('1s:00:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('00:60:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('00:e0:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('00:00:60') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('00:00:w0') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00:00.00w') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00:00+01b00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00:00+0w:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00:00+20:00') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00:00+01:0w') with self.assertRaises(ValueError): time_elements_object._CopyTimeFromStringISO8601('12:00:00+01:60') def testCopyFromString(self): """Tests the CopyFromString function.""" time_elements_object = time_elements.TimeElements() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromString('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" time_elements_object = time_elements.TimeElements() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 22, 6, 31) expected_number_of_seconds = 1281650791 time_elements_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) expected_number_of_seconds = 1281643591 time_elements_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0) expected_number_of_seconds = -11644387200 time_elements_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) def testCopyFromStringISO8601(self): """Tests the CopyFromStringISO8601 function.""" time_elements_object = time_elements.TimeElements() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromStringISO8601('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31Z') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.5') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31,546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0) expected_number_of_seconds = 1330980000 time_elements_object.CopyFromStringISO8601('2012-03-05T20:40:00.0000000Z') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 22, 6, 31) expected_number_of_seconds = 1281650791 time_elements_object.CopyFromStringISO8601( '2010-08-12T21:06:31.546875-01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) expected_number_of_seconds = 1281643591 time_elements_object.CopyFromStringISO8601( '2010-08-12T21:06:31.546875+01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601(None) with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601( '2010-08-12 21:06:31.546875+01:00') # Valid ISO 8601 notations currently not supported. with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-W33') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-W33-3') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('--08-17') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-230') def testCopyFromStringTuple(self): """Tests the CopyFromStringTuple function.""" time_elements_object = time_elements.TimeElements() expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31')) self.assertIsNotNone(time_elements_object) self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('20A0', 'B', '12', '20', '6', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', 'B', '12', '20', '6', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '1C', '20', '6', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', 'D0', '6', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', 'E', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', 'F1')) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" time_elements_object = time_elements.TimeElements( time_elements_tuple=(2010, 8, 12, 20, 6, 31)) expected_stat_time_tuple = (1281643591, None) stat_time_tuple = time_elements_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) time_elements_object = time_elements.TimeElements() expected_stat_time_tuple = (None, None) stat_time_tuple = time_elements_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" time_elements_object = time_elements.TimeElements( time_elements_tuple=(2010, 8, 12, 20, 6, 31)) date_time_string = time_elements_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31') time_elements_object = time_elements.TimeElements() date_time_string = time_elements_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" time_elements_object = time_elements.TimeElements( time_elements_tuple=(2010, 8, 12, 20, 6, 31)) expected_micro_posix_number_of_seconds = 1281643591000000 micro_posix_number_of_seconds = time_elements_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) time_elements_object = time_elements.TimeElements() micro_posix_number_of_seconds = time_elements_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_number_of_seconds) class TimeElementsInMillisecondsTest(unittest.TestCase): """Tests for the time elements in milliseconds.""" # pylint: disable=protected-access def testInitialize(self): """Tests the initialization function.""" time_elements_object = time_elements.TimeElements() self.assertIsNotNone(time_elements_object) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) time_elements_object = time_elements.TimeElementsInMilliseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 546)) self.assertIsNotNone(time_elements_object) self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual(time_elements_object.milliseconds, 546) with self.assertRaises(ValueError): time_elements.TimeElementsInMilliseconds( time_elements_tuple=(2010, 13, 12, 20, 6, 31)) with self.assertRaises(ValueError): time_elements.TimeElementsInMilliseconds( time_elements_tuple=(2010, 13, 12, 20, 6, 31, 1001)) # TODO: add tests for _CopyFromDateTimeValues def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" time_elements_object = time_elements.TimeElementsInMilliseconds() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) expected_time_elements_tuple = (2010, 8, 12, 22, 6, 31) expected_number_of_seconds = 1281650791 time_elements_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) expected_number_of_seconds = 1281643591 time_elements_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0) expected_number_of_seconds = -11644387200 time_elements_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) def testCopyFromStringISO8601(self): """Tests the CopyFromStringISO8601 function.""" time_elements_object = time_elements.TimeElementsInMilliseconds() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromStringISO8601('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31Z') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.5') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 500) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31,546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0) expected_number_of_seconds = 1330980000 time_elements_object.CopyFromStringISO8601('2012-03-05T20:40:00.0000000Z') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 22, 6, 31) expected_number_of_seconds = 1281650791 time_elements_object.CopyFromStringISO8601( '2010-08-12T21:06:31.546875-01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) expected_number_of_seconds = 1281643591 time_elements_object.CopyFromStringISO8601( '2010-08-12T21:06:31.546875+01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.milliseconds, 546) with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601(None) with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601( '2010-08-12 21:06:31.546875+01:00') # Valid ISO 8601 notations currently not supported. with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-W33') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-W33-3') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('--08-17') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-230') def testCopyFromStringTuple(self): """Tests the CopyFromStringTuple function.""" time_elements_object = time_elements.TimeElementsInMilliseconds() expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31', '546')) self.assertIsNotNone(time_elements_object) self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual(time_elements_object.milliseconds, 546) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31', '9S')) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" time_elements_object = time_elements.TimeElementsInMilliseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429)) expected_stat_time_tuple = (1281643591, 4290000) stat_time_tuple = time_elements_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) time_elements_object = time_elements.TimeElementsInMilliseconds() expected_stat_time_tuple = (None, None) stat_time_tuple = time_elements_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" time_elements_object = time_elements.TimeElementsInMilliseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429)) date_time_string = time_elements_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31.429') time_elements_object = time_elements.TimeElementsInMilliseconds() date_time_string = time_elements_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" time_elements_object = time_elements.TimeElementsInMilliseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429)) expected_micro_posix_number_of_seconds = 1281643591429000 micro_posix_number_of_seconds = time_elements_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) time_elements_object = time_elements.TimeElementsInMilliseconds() micro_posix_number_of_seconds = time_elements_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_number_of_seconds) class TimeElementsInMicrosecondsTest(unittest.TestCase): """Tests for the time elements in microseconds.""" # pylint: disable=protected-access def testInitialize(self): """Tests the initialization function.""" time_elements_object = time_elements.TimeElements() self.assertIsNotNone(time_elements_object) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) time_elements_object = time_elements.TimeElementsInMicroseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 546)) self.assertIsNotNone(time_elements_object) self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual(time_elements_object.microseconds, 546) with self.assertRaises(ValueError): time_elements.TimeElementsInMicroseconds( time_elements_tuple=(2010, 13, 12, 20, 6, 31)) with self.assertRaises(ValueError): time_elements.TimeElementsInMicroseconds( time_elements_tuple=(2010, 13, 12, 20, 6, 31, 1001)) # TODO: add tests for _CopyFromDateTimeValues def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" time_elements_object = time_elements.TimeElementsInMicroseconds() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromDateTimeString('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) expected_time_elements_tuple = (2010, 8, 12, 22, 6, 31) expected_number_of_seconds = 1281650791 time_elements_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) expected_number_of_seconds = 1281643591 time_elements_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0) expected_number_of_seconds = -11644387200 time_elements_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) def testCopyFromStringISO8601(self): """Tests the CopyFromStringISO8601 function.""" time_elements_object = time_elements.TimeElementsInMicroseconds() expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0) expected_number_of_seconds = 1281571200 time_elements_object.CopyFromStringISO8601('2010-08-12') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31Z') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.5') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 500000) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31) expected_number_of_seconds = 1281647191 time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31,546875') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0) expected_number_of_seconds = 1330980000 time_elements_object.CopyFromStringISO8601('2012-03-05T20:40:00.0000000Z') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 0) expected_time_elements_tuple = (2010, 8, 12, 22, 6, 31) expected_number_of_seconds = 1281650791 time_elements_object.CopyFromStringISO8601( '2010-08-12T21:06:31.546875-01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) expected_number_of_seconds = 1281643591 time_elements_object.CopyFromStringISO8601( '2010-08-12T21:06:31.546875+01:00') self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual( time_elements_object._number_of_seconds, expected_number_of_seconds) self.assertEqual(time_elements_object.microseconds, 546875) with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601(None) with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601( '2010-08-12 21:06:31.546875+01:00') # Valid ISO 8601 notations currently not supported. with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-W33') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-W33-3') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('--08-17') with self.assertRaises(ValueError): time_elements_object.CopyFromStringISO8601('2016-230') def testCopyFromStringTuple(self): """Tests the CopyFromStringTuple function.""" time_elements_object = time_elements.TimeElementsInMicroseconds() expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31) time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31', '546')) self.assertIsNotNone(time_elements_object) self.assertEqual( time_elements_object._time_elements_tuple, expected_time_elements_tuple) self.assertEqual(time_elements_object.microseconds, 546) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31')) with self.assertRaises(ValueError): time_elements_object.CopyFromStringTuple( time_elements_tuple=('2010', '8', '12', '20', '6', '31', '9S')) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" time_elements_object = time_elements.TimeElementsInMicroseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876)) expected_stat_time_tuple = (1281643591, 4298760) stat_time_tuple = time_elements_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) time_elements_object = time_elements.TimeElementsInMicroseconds() expected_stat_time_tuple = (None, None) stat_time_tuple = time_elements_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" time_elements_object = time_elements.TimeElementsInMicroseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876)) date_time_string = time_elements_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 20:06:31.429876') time_elements_object = time_elements.TimeElementsInMicroseconds() date_time_string = time_elements_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" time_elements_object = time_elements.TimeElementsInMicroseconds( time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876)) expected_micro_posix_number_of_seconds = 1281643591429876 micro_posix_number_of_seconds = time_elements_object.GetPlasoTimestamp() self.assertEqual( micro_posix_number_of_seconds, expected_micro_posix_number_of_seconds) time_elements_object = time_elements.TimeElementsInMicroseconds() micro_posix_number_of_seconds = time_elements_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_number_of_seconds) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/uuid_time.py000066400000000000000000000115261322532640600175660ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the UUID version 1 timestamp implementation.""" from __future__ import unicode_literals import uuid import unittest from dfdatetime import uuid_time class UUIDTimeTest(unittest.TestCase): """Tests for the UUID version 1 timestamp.""" def testInitialize(self): """Tests the initialization function.""" uuid_time_object = uuid_time.UUIDTime() self.assertIsNotNone(uuid_time_object) uuid_object = uuid.UUID('00911b54-9ef4-11e1-be53-525400123456') uuid_time_object = uuid_time.UUIDTime(timestamp=uuid_object.time) self.assertIsNotNone(uuid_time_object) expected_timestamp = 135564234616544084 self.assertEqual(uuid_time_object.timestamp, expected_timestamp) with self.assertRaises(ValueError): uuid_time.UUIDTime(timestamp=0x1fffffffffffffff) with self.assertRaises(ValueError): uuid_time.UUIDTime(timestamp=-1) def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" uuid_time_object = uuid_time.UUIDTime() expected_timestamp = 135946080000000000 uuid_time_object.CopyFromDateTimeString('2013-08-01') self.assertEqual(uuid_time_object.timestamp, expected_timestamp) expected_timestamp = 135946635280000000 uuid_time_object.CopyFromDateTimeString('2013-08-01 15:25:28') self.assertEqual(uuid_time_object.timestamp, expected_timestamp) expected_timestamp = 135946635285468750 uuid_time_object.CopyFromDateTimeString('2013-08-01 15:25:28.546875') self.assertEqual(uuid_time_object.timestamp, expected_timestamp) expected_timestamp = 135946671285468750 uuid_time_object.CopyFromDateTimeString('2013-08-01 15:25:28.546875-01:00') self.assertEqual(uuid_time_object.timestamp, expected_timestamp) expected_timestamp = 135946599285468750 uuid_time_object.CopyFromDateTimeString('2013-08-01 15:25:28.546875+01:00') self.assertEqual(uuid_time_object.timestamp, expected_timestamp) expected_timestamp = 864000000000 uuid_time_object.CopyFromDateTimeString('1582-10-16 00:00:00') self.assertEqual(uuid_time_object.timestamp, expected_timestamp) with self.assertRaises(ValueError): uuid_time_object.CopyFromDateTimeString('1570-01-02 00:00:00') def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" uuid_object = uuid.UUID('00911b54-9ef4-11e1-be53-525400123456') uuid_time_object = uuid_time.UUIDTime(timestamp=uuid_object.time) expected_stat_time_tuple = (1337130661, 6544084) stat_time_tuple = uuid_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) uuid_time_object = uuid_time.UUIDTime() uuid_time_object.timestamp = 0x1fffffffffffffff expected_stat_time_tuple = (None, None) stat_time_tuple = uuid_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) uuid_time_object = uuid_time.UUIDTime() uuid_time_object.timestamp = -1 expected_stat_time_tuple = (None, None) stat_time_tuple = uuid_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) uuid_time_object = uuid_time.UUIDTime() expected_stat_time_tuple = (None, None) stat_time_tuple = uuid_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" uuid_object = uuid.UUID('00911b54-9ef4-11e1-be53-525400123456') uuid_time_object = uuid_time.UUIDTime(timestamp=uuid_object.time) date_time_string = uuid_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2012-05-16 01:11:01.6544084') uuid_time_object = uuid_time.UUIDTime() date_time_string = uuid_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" uuid_object = uuid.UUID('00911b54-9ef4-11e1-be53-525400123456') uuid_time_object = uuid_time.UUIDTime(timestamp=uuid_object.time) expected_micro_posix_timestamp = 1337130661654408 micro_posix_timestamp = uuid_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) uuid_time_object = uuid_time.UUIDTime() uuid_time_object.timestamp = 0x1fffffffffffffff micro_posix_timestamp = uuid_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) uuid_time_object = uuid_time.UUIDTime() uuid_time_object.timestamp = -1 micro_posix_timestamp = uuid_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) uuid_time_object = uuid_time.UUIDTime() micro_posix_timestamp = uuid_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tests/webkit_time.py000066400000000000000000000070231322532640600201020ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Tests for the WebKit timestamp implementation.""" from __future__ import unicode_literals import unittest from dfdatetime import webkit_time class WebKitTimeTest(unittest.TestCase): """Tests for the WebKit timestamp.""" def testCopyFromDateTimeString(self): """Tests the CopyFromDateTimeString function.""" webkit_time_object = webkit_time.WebKitTime() expected_timestamp = 12926044800000000 webkit_time_object.CopyFromDateTimeString('2010-08-12') self.assertEqual(webkit_time_object.timestamp, expected_timestamp) expected_timestamp = 12926120791000000 webkit_time_object.CopyFromDateTimeString('2010-08-12 21:06:31') self.assertEqual(webkit_time_object.timestamp, expected_timestamp) expected_timestamp = 12926120791546875 webkit_time_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875') self.assertEqual(webkit_time_object.timestamp, expected_timestamp) expected_timestamp = 12926124391546875 webkit_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875-01:00') self.assertEqual(webkit_time_object.timestamp, expected_timestamp) expected_timestamp = 12926117191546875 webkit_time_object.CopyFromDateTimeString( '2010-08-12 21:06:31.546875+01:00') self.assertEqual(webkit_time_object.timestamp, expected_timestamp) expected_timestamp = 86400 * 1000000 webkit_time_object.CopyFromDateTimeString('1601-01-02 00:00:00') self.assertEqual(webkit_time_object.timestamp, expected_timestamp) def testCopyToStatTimeTuple(self): """Tests the CopyToStatTimeTuple function.""" webkit_time_object = webkit_time.WebKitTime(timestamp=12926120791546875) expected_stat_time_tuple = (1281647191, 5468750) stat_time_tuple = webkit_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) webkit_time_object = webkit_time.WebKitTime(timestamp=0x1ffffffffffffffff) expected_stat_time_tuple = (None, None) stat_time_tuple = webkit_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) webkit_time_object = webkit_time.WebKitTime() expected_stat_time_tuple = (None, None) stat_time_tuple = webkit_time_object.CopyToStatTimeTuple() self.assertEqual(stat_time_tuple, expected_stat_time_tuple) def testCopyToDateTimeString(self): """Tests the CopyToDateTimeString function.""" webkit_time_object = webkit_time.WebKitTime(timestamp=12926120791546875) date_time_string = webkit_time_object.CopyToDateTimeString() self.assertEqual(date_time_string, '2010-08-12 21:06:31.546875') webkit_time_object = webkit_time.WebKitTime() date_time_string = webkit_time_object.CopyToDateTimeString() self.assertIsNone(date_time_string) def testGetPlasoTimestamp(self): """Tests the GetPlasoTimestamp function.""" webkit_time_object = webkit_time.WebKitTime(timestamp=12926120791546875) expected_micro_posix_timestamp = 1281647191546875 micro_posix_timestamp = webkit_time_object.GetPlasoTimestamp() self.assertEqual(micro_posix_timestamp, expected_micro_posix_timestamp) webkit_time_object = webkit_time.WebKitTime(timestamp=0x1ffffffffffffffff) micro_posix_timestamp = webkit_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) webkit_time_object = webkit_time.WebKitTime() micro_posix_timestamp = webkit_time_object.GetPlasoTimestamp() self.assertIsNone(micro_posix_timestamp) if __name__ == '__main__': unittest.main() dfdatetime-20180110/tox.ini000066400000000000000000000006611322532640600153770ustar00rootroot00000000000000[tox] envlist = py2, py3 [testenv] pip_pre = True setenv = PYTHONPATH = {toxinidir} deps = coverage mock pytest -rrequirements.txt commands = ./run_tests.py [testenv:py27] pip_pre = True setenv = PYTHONPATH = {toxinidir} deps = coverage mock pytest -rrequirements.txt commands = coverage erase coverage run --source=dfdatetime --omit="*_test*,*__init__*,*test_lib*" run_tests.py dfdatetime-20180110/utils/000077500000000000000000000000001322532640600152215ustar00rootroot00000000000000dfdatetime-20180110/utils/__init__.py000066400000000000000000000000301322532640600173230ustar00rootroot00000000000000# -*- coding: utf-8 -*- dfdatetime-20180110/utils/check_dependencies.py000077500000000000000000000006121322532640600213600ustar00rootroot00000000000000#!/usr/bin/python # -*- coding: utf-8 -*- """Script to check for the availability and version of dependencies.""" import sys # Change PYTHONPATH to include dependencies. sys.path.insert(0, '.') import utils.dependencies # pylint: disable=wrong-import-position if __name__ == '__main__': dependency_helper = utils.dependencies.DependencyHelper() dependency_helper.CheckDependencies() dfdatetime-20180110/utils/dependencies.py000066400000000000000000000277361322532640600202400ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Helper to check for availability and version of dependencies.""" from __future__ import print_function from __future__ import unicode_literals import re try: import ConfigParser as configparser except ImportError: import configparser # pylint: disable=import-error class DependencyDefinition(object): """Dependency definition. Attributes: dpkg_name (str): name of the dpkg package that provides the dependency. is_optional (bool): True if the dependency is optional. l2tbinaries_name (str): name of the l2tbinaries package that provides the dependency. maximum_version (str): maximum supported version. minimum_version (str): minimum supported version. name (str): name of (the Python module that provides) the dependency. pypi_name (str): name of the PyPI package that provides the dependency. python2_only (bool): True if the dependency is only supported by Python 2. rpm_name (str): name of the rpm package that provides the dependency. version_property (str): name of the version attribute or function. """ def __init__(self, name): """Initializes a dependency configuation. Args: name (str): name of the dependency. """ super(DependencyDefinition, self).__init__() self.dpkg_name = None self.is_optional = False self.l2tbinaries_name = None self.maximum_version = None self.minimum_version = None self.name = name self.pypi_name = None self.python2_only = False self.rpm_name = None self.version_property = None class DependencyDefinitionReader(object): """Dependency definition reader.""" _VALUE_NAMES = frozenset([ 'dpkg_name', 'is_optional', 'l2tbinaries_name', 'maximum_version', 'minimum_version', 'pypi_name', 'python2_only', 'rpm_name', 'version_property']) def _GetConfigValue(self, config_parser, section_name, value_name): """Retrieves a value from the config parser. Args: config_parser (ConfigParser): configuration parser. section_name (str): name of the section that contains the value. value_name (str): name of the value. Returns: object: configuration value or None if the value does not exists. """ try: return config_parser.get(section_name, value_name) except configparser.NoOptionError: return def Read(self, file_object): """Reads dependency definitions. Args: file_object (file): file-like object to read from. Yields: DependencyDefinition: dependency definition. """ config_parser = configparser.RawConfigParser() # pylint: disable=deprecated-method # TODO: replace readfp by read_file, check if Python 2 compatible config_parser.readfp(file_object) for section_name in config_parser.sections(): dependency_definition = DependencyDefinition(section_name) for value_name in self._VALUE_NAMES: value = self._GetConfigValue(config_parser, section_name, value_name) setattr(dependency_definition, value_name, value) yield dependency_definition class DependencyHelper(object): """Dependency helper.""" _VERSION_NUMBERS_REGEX = re.compile(r'[0-9.]+') _VERSION_SPLIT_REGEX = re.compile(r'\.|\-') def __init__(self, configuration_file='dependencies.ini'): """Initializes a dependency helper. Args: configuration_file (Optional[str]): path to the dependencies configuration file. """ super(DependencyHelper, self).__init__() self._dependencies = {} self._test_dependencies = {} dependency_reader = DependencyDefinitionReader() with open(configuration_file, 'r') as file_object: for dependency in dependency_reader.Read(file_object): self._dependencies[dependency.name] = dependency dependency = DependencyDefinition('mock') dependency.minimum_version = '0.7.1' dependency.version_property = '__version__' self._test_dependencies['mock'] = dependency def _CheckPythonModule(self, dependency): """Checks the availability of a Python module. Args: dependency (DependencyDefinition): dependency definition. Returns: tuple: consists: bool: True if the Python module is available and conforms to the minimum required version, False otherwise. str: status message. """ module_object = self._ImportPythonModule(dependency.name) if not module_object: status_message = 'missing: {0:s}'.format(dependency.name) return dependency.is_optional, status_message if not dependency.version_property or not dependency.minimum_version: return True, dependency.name return self._CheckPythonModuleVersion( dependency.name, module_object, dependency.version_property, dependency.minimum_version, dependency.maximum_version) def _CheckPythonModuleVersion( self, module_name, module_object, version_property, minimum_version, maximum_version): """Checks the version of a Python module. Args: module_object (module): Python module. module_name (str): name of the Python module. version_property (str): version attribute or function. minimum_version (str): minimum version. maximum_version (str): maximum version. Returns: tuple: consists: bool: True if the Python module is available and conforms to the minimum required version, False otherwise. str: status message. """ module_version = None if not version_property.endswith('()'): module_version = getattr(module_object, version_property, None) else: version_method = getattr( module_object, version_property[:-2], None) if version_method: module_version = version_method() if not module_version: status_message = ( 'unable to determine version information for: {0:s}').format( module_name) return False, status_message # Make sure the module version is a string. module_version = '{0!s}'.format(module_version) # Split the version string and convert every digit into an integer. # A string compare of both version strings will yield an incorrect result. # Strip any semantic suffixes such as a1, b1, pre, post, rc, dev. module_version = self._VERSION_NUMBERS_REGEX.findall(module_version)[0] if module_version[-1] == '.': module_version = module_version[:-1] try: module_version_map = list( map(int, self._VERSION_SPLIT_REGEX.split(module_version))) except ValueError: status_message = 'unable to parse module version: {0:s} {1:s}'.format( module_name, module_version) return False, status_message try: minimum_version_map = list( map(int, self._VERSION_SPLIT_REGEX.split(minimum_version))) except ValueError: status_message = 'unable to parse minimum version: {0:s} {1:s}'.format( module_name, minimum_version) return False, status_message if module_version_map < minimum_version_map: status_message = ( '{0:s} version: {1!s} is too old, {2!s} or later required').format( module_name, module_version, minimum_version) return False, status_message if maximum_version: try: maximum_version_map = list( map(int, self._VERSION_SPLIT_REGEX.split(maximum_version))) except ValueError: status_message = 'unable to parse maximum version: {0:s} {1:s}'.format( module_name, maximum_version) return False, status_message if module_version_map > maximum_version_map: status_message = ( '{0:s} version: {1!s} is too recent, {2!s} or earlier ' 'required').format(module_name, module_version, maximum_version) return False, status_message status_message = '{0:s} version: {1!s}'.format(module_name, module_version) return True, status_message def _CheckSQLite3(self): """Checks the availability of sqlite3. Returns: tuple: consists: bool: True if the Python module is available and conforms to the minimum required version, False otherwise. str: status message. """ # On Windows sqlite3 can be provided by both pysqlite2.dbapi2 and # sqlite3. sqlite3 is provided with the Python installation and # pysqlite2.dbapi2 by the pysqlite2 Python module. Typically # pysqlite2.dbapi2 would contain a newer version of sqlite3, hence # we check for its presence first. module_name = 'pysqlite2.dbapi2' minimum_version = '3.7.8' module_object = self._ImportPythonModule(module_name) if not module_object: module_name = 'sqlite3' module_object = self._ImportPythonModule(module_name) if not module_object: status_message = 'missing: {0:s}.'.format(module_name) return False, status_message return self._CheckPythonModuleVersion( module_name, module_object, 'sqlite_version', minimum_version, None) def _ImportPythonModule(self, module_name): """Imports a Python module. Args: module_name (str): name of the module. Returns: module: Python module or None if the module cannot be imported. """ try: module_object = list(map(__import__, [module_name]))[0] except ImportError: return # If the module name contains dots get the upper most module object. if '.' in module_name: for submodule_name in module_name.split('.')[1:]: module_object = getattr(module_object, submodule_name, None) return module_object def _PrintCheckDependencyStatus( self, dependency, result, status_message, verbose_output=True): """Prints the check dependency status. Args: dependency (DependencyDefinition): dependency definition. result (bool): True if the Python module is available and conforms to the minimum required version, False otherwise. status_message (str): status message. """ if not result or dependency.is_optional: if dependency.is_optional: status_indicator = '[OPTIONAL]' else: status_indicator = '[FAILURE]' print('{0:s}\t{1:s}.'.format(status_indicator, status_message)) elif verbose_output: print('[OK]\t\t{0:s}'.format(status_message)) def CheckDependencies(self, verbose_output=True): """Checks the availability of the dependencies. Args: verbose_output (Optional[bool]): True if output should be verbose. Returns: bool: True if the dependencies are available, False otherwise. """ print('Checking availability and versions of dependencies.') check_result = True for module_name, dependency in sorted(self._dependencies.items()): if module_name == 'sqlite3': result, status_message = self._CheckSQLite3() else: result, status_message = self._CheckPythonModule(dependency) if not result: check_result = False self._PrintCheckDependencyStatus( dependency, result, status_message, verbose_output=verbose_output) if check_result and not verbose_output: print('[OK]') print('') return check_result def CheckTestDependencies(self, verbose_output=True): """Checks the availability of the dependencies when running tests. Args: verbose_output (Optional[bool]): True if output should be verbose. Returns: bool: True if the dependencies are available, False otherwise. """ if not self.CheckDependencies(verbose_output=verbose_output): return False print('Checking availability and versions of test dependencies.') check_result = True for dependency in sorted( self._test_dependencies.values(), key=lambda dependency: dependency.name): result, status_message = self._CheckPythonModule(dependency) if not result: check_result = False self._PrintCheckDependencyStatus( dependency, result, status_message, verbose_output=verbose_output) if check_result and not verbose_output: print('[OK]') print('') return check_result