#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Tests for the time elements implementation."""

import datetime
import decimal
import unittest

from dfdatetime import definitions
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)
    self.assertEqual(time_elements_object.year, 2010)
    self.assertEqual(time_elements_object.month, 8)
    self.assertEqual(time_elements_object.day_of_month, 12)
    self.assertEqual(time_elements_object.hours, 20)
    self.assertEqual(time_elements_object.minutes, 6)
    self.assertEqual(time_elements_object.seconds, 31)

    expected_time_elements_tuple = (2010, 2, 29, 20, 6, 31)
    time_elements_object = time_elements.TimeElements(
        is_delta=True, time_elements_tuple=(2010, 2, 29, 20, 6, 31))
    self.assertIsNotNone(time_elements_object)
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object.year, 2010)
    self.assertEqual(time_elements_object.month, 2)
    self.assertEqual(time_elements_object.day_of_month, 29)
    self.assertEqual(time_elements_object.hours, 20)
    self.assertEqual(time_elements_object.minutes, 6)
    self.assertEqual(time_elements_object.seconds, 31)
    self.assertTrue(time_elements_object.is_delta)

    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, 2, 29, 20, 6))

    with self.assertRaises(ValueError):
      time_elements.TimeElements(
          time_elements_tuple=(2010, 13, 12, 20, 6, 31))

  def testGetNormalizedTimestamp(self):
    """Tests the _GetNormalizedTimestamp function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281643591'))

    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31), time_zone_offset=60)

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991'))

    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))
    time_elements_object.time_zone_offset = 60

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991'))

    time_elements_object = time_elements.TimeElements()

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertIsNone(normalized_timestamp)

  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, 'nanoseconds': 546875000}
    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': 21, 'minutes': 6, 'seconds': 31, 'nanoseconds': 546875000,
        'time_zone_offset': -60}
    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': 21, 'minutes': 6, 'seconds': 31, 'nanoseconds': 546875000,
        'time_zone_offset': 60}
    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': 21, 'minutes': 6, 'seconds': 31, 'nanoseconds': 546875333,
        'time_zone_offset': 60}
    date_dict = time_elements_object._CopyDateTimeFromStringISO8601(
        '2010-08-12T21:06:31.546875333+01:00')
    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')

  def testCopyDateTimeFromStringRFC822(self):
    """Tests the _CopyDateTimeFromStringRFC822 function."""
    time_elements_object = time_elements.TimeElements()

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': 0}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC822(
        'Sun, 20 Jun 82 11:57:09 GMT')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': 0}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC822(
        '20 Jun 82 11:57:09 GMT')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57,
        'time_zone_offset': 0}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC822(
        '20 Jun 82 11:57 GMT')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': -300}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC822(
        'Sun, 20 Jun 82 11:57:09 EST')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': -300}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC822(
        'Sun, 20 Jun 82 11:57:09 -0500')
    self.assertEqual(date_dict, expected_date_dict)

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC822(
          'XXX, 20 Jun 82 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC822(
          'Sun, XX Jun 82 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC822(
          'Sun, 20 XXX 82 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC822(
          'Sun, 20 Jun XX 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC822(
          'Sun, 20 Jun 82 XX:XX:XX XXX')

  def testCopyDateTimeFromStringRFC1123(self):
    """Tests the _CopyDateTimeFromStringRFC1123 function."""
    time_elements_object = time_elements.TimeElements()

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': 0}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC1123(
        'Sun, 20 Jun 1982 11:57:09 GMT')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': 0}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC1123(
        '20 Jun 1982 11:57:09 GMT')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57,
        'time_zone_offset': 0}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC1123(
        '20 Jun 1982 11:57 GMT')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': -300}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC1123(
        'Sun, 20 Jun 1982 11:57:09 EST')
    self.assertEqual(date_dict, expected_date_dict)

    expected_date_dict = {
        'year': 1982, 'month': 6, 'day_of_month': 20,
        'hours': 11, 'minutes': 57, 'seconds': 9,
        'time_zone_offset': -300}
    date_dict = time_elements_object._CopyDateTimeFromStringRFC1123(
        'Sun, 20 Jun 1982 11:57:09 -0500')
    self.assertEqual(date_dict, expected_date_dict)

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC1123(
          'XXX, 20 Jun 1982 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC1123(
          'Sun, XX Jun 1982 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC1123(
          'Sun, 20 XXX 1982 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC1123(
          'Sun, 20 Jun XXXX 11:57:09 GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyDateTimeFromStringRFC1123(
          'Sun, 20 Jun 1982 XX:XX:XX XXX')

  # 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 = (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, 327000000, None)
    time_tuple = time_elements_object._CopyTimeFromStringISO8601('20:23:56.327')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (20, 23, 56, 327000000, 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, 327124000, None)
    time_tuple = time_elements_object._CopyTimeFromStringISO8601(
        '20:23:56.327124')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (8, 4, 32, None, 0)
    time_tuple = time_elements_object._CopyTimeFromStringISO8601('08:04:32Z')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (8, 4, 32, None, 0)
    time_tuple = time_elements_object._CopyTimeFromStringISO8601(
        '08:04:32+00:00')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (20, 23, 56, 327124000, -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 testCopyTimeFromStringRFC(self):
    """Tests the _CopyTimeFromStringRFC function."""
    time_elements_object = time_elements.TimeElements()

    expected_time_tuple = (11, 57, 9, 0)
    time_tuple = time_elements_object._CopyTimeFromStringRFC('11:57:09', 'GMT')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (11, 57, None, 0)
    time_tuple = time_elements_object._CopyTimeFromStringRFC('11:57', 'GMT')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (11, 57, None, -300)
    time_tuple = time_elements_object._CopyTimeFromStringRFC('11:57', 'EST')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (11, 57, None, -300)
    time_tuple = time_elements_object._CopyTimeFromStringRFC('11:57', '-0500')
    self.assertEqual(time_tuple, expected_time_tuple)

    expected_time_tuple = (11, 57, None, 60)
    time_tuple = time_elements_object._CopyTimeFromStringRFC('11:57', '+0100')
    self.assertEqual(time_tuple, expected_time_tuple)

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:57:', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('XX:57:09', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('24:57:09', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:XX:09', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:60:09', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:57:XX', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:57:60', 'GMT')

    with self.assertRaises(ValueError):
      time_elements_object._CopyTimeFromStringRFC('11:57:09', 'XXX')

  def testCopyFromDatetime(self):
    """Tests the CopyFromDatetime function."""
    time_elements_object = time_elements.TimeElements()

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    datetime_object = datetime.datetime(2010, 8, 12, 21, 6, 31, 546875)
    time_elements_object.CopyFromDatetime(datetime_object)
    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.assertTrue(time_elements_object.is_local_time)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    datetime_object = datetime.datetime(
        2010, 8, 12, 21, 6, 31, 546875, tzinfo=datetime.timezone.utc)
    time_elements_object.CopyFromDatetime(datetime_object)
    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.assertFalse(time_elements_object.is_local_time)

  def testCopyFromDateTimeString(self):
    """Tests the CopyFromDateTimeString function."""
    time_elements_object = time_elements.TimeElements()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0)
    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, -11644387200)
    self.assertEqual(time_elements_object._time_zone_offset, None)

  def testCopyFromStringISO8601(self):
    """Tests the CopyFromStringISO8601 function."""
    time_elements_object = time_elements.TimeElements()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0)
    time_elements_object.CopyFromStringISO8601(
        '2012-03-05T20:40:00.0000000+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1330980000)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    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 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(
        time_elements_tuple=(0, 8, 12, 20, 6, 31))

    date_time_string = time_elements_object.CopyToDateTimeString()
    self.assertEqual(date_time_string, '0000-08-12 20:06:31')

    time_elements_object = time_elements.TimeElements()

    date_time_string = time_elements_object.CopyToDateTimeString()
    self.assertIsNone(date_time_string)

  def testCopyToDateTimeStringISO8601(self):
    """Tests the CopyToDateTimeStringISO8601 function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31+00:00')

    time_elements_object.is_local_time = True

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31')

    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31),
        time_zone_offset=120)

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31+02:00')

    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31),
        time_zone_offset=-300)

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31-05:00')

  def testCopyToPosixTimestamp(self):
    """Tests the CopyToPosixTimestamp function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertEqual(posix_timestamp, 1281643591)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertIsNone(posix_timestamp)

  def testCopyToPosixTimestampWithFractionOfSecond(self):
    """Tests the CopyToPosixTimestampWithFractionOfSecond function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertEqual(posix_timestamp, 1281643591)
    self.assertIsNone(fraction_of_second)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertIsNone(posix_timestamp)
    self.assertIsNone(fraction_of_second)

  def testGetDate(self):
    """Tests the GetDate function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (2010, 8, 12))

    time_elements_object = time_elements.TimeElements()

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (None, None, None))

  def testGetDateWithTimeOfDay(self):
    """Tests the GetDateWithTimeOfDay function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(date_with_time_of_day_tuple, (2010, 8, 12, 20, 6, 31))

    time_elements_object = time_elements.TimeElements()

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(
        date_with_time_of_day_tuple, (None, None, None, None, None, None))

  def testGetTimeOfDay(self):
    """Tests the GetTimeOfDay function."""
    time_elements_object = time_elements.TimeElements(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (20, 6, 31))

    time_elements_object = time_elements.TimeElements()

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (None, None, None))

  def testNewFromDeltaAndDate(self):
    """Tests the NewFromDeltaAndDate function."""
    time_elements_object = time_elements.TimeElements(
        is_delta=True, time_elements_tuple=(1, 0, 0, 20, 6, 31))

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.month, 1)
    self.assertEqual(new_time_elements_object.day_of_month, 12)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndDate(2009, 1, 12)

  def testNewFromDeltaAndYear(self):
    """Tests the NewFromDeltaAndYear function."""
    time_elements_object = time_elements.TimeElements(
        is_delta=True, time_elements_tuple=(1, 8, 12, 20, 6, 31))

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndYear(2009)


class TimeElementsWithFractionOfSeconds(unittest.TestCase):
  """Tests for the time elements with fractions of seconds."""

  # pylint: disable=protected-access

  def testInitialize(self):
    """Tests the initialization function."""
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond()
    self.assertIsNotNone(time_elements_object)

    expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31)
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal(0.87),
        precision=definitions.PRECISION_10_MILLISECONDS,
        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)
    self.assertEqual(time_elements_object.fraction_of_second, 0.87)

    expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31)
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal(0.8742),
        precision=definitions.PRECISION_100_MICROSECONDS,
        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)
    self.assertEqual(time_elements_object.fraction_of_second, 0.8742)

    with self.assertRaises(ValueError):
      time_elements.TimeElementsWithFractionOfSecond(
          fraction_of_second=decimal.Decimal('1.87'),
          precision=definitions.PRECISION_10_MILLISECONDS,
          time_elements_tuple=(2010, 8, 12, 20, 6, 31))

    with self.assertRaises(ValueError):
      time_elements.TimeElementsWithFractionOfSecond(
          fraction_of_second=decimal.Decimal('-1'),
          precision=definitions.PRECISION_10_MILLISECONDS,
          time_elements_tuple=(2010, 8, 12, 20, 6, 31))

  def testGetNormalizedTimestamp(self):
    """Tests the _GetNormalizedTimestamp function."""
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.87'),
        precision=definitions.PRECISION_10_MILLISECONDS,
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))
    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281643591.87'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.87'),
        precision=definitions.PRECISION_10_MILLISECONDS,
        time_elements_tuple=(2010, 8, 12, 20, 6, 31),
        time_zone_offset=60)
    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991.87'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.87'),
        precision=definitions.PRECISION_10_MILLISECONDS,
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))
    time_elements_object.time_zone_offset = 60
    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991.87'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.8724'),
        precision=definitions.PRECISION_100_MICROSECONDS,
        time_elements_tuple=(2010, 8, 12, 20, 6, 31))
    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281643591.8724'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond()
    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertIsNone(normalized_timestamp)

  def testCopyFromDateTimeValues(self):
    """Tests the _CopyFromDateTimeValues function."""
    date_time_values = {
        'year': 2010,
        'month': 8,
        'day_of_month': 12,
        'hours': 21,
        'minutes': 6,
        'seconds': 31,
        'nanoseconds': 123456789,
        'time_zone_offset': 60}

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        precision=definitions.PRECISION_10_MILLISECONDS)
    time_elements_object._CopyFromDateTimeValues(date_time_values)

    self.assertEqual(
      time_elements_object._time_elements_tuple, (2010, 8, 12, 21, 6, 31))
    self.assertEqual(
      time_elements_object.fraction_of_second, decimal.Decimal('0.12'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        precision=definitions.PRECISION_1_MILLISECOND)
    time_elements_object._CopyFromDateTimeValues(date_time_values)
    self.assertEqual(
      time_elements_object.fraction_of_second, decimal.Decimal('0.123'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        precision=definitions.PRECISION_100_MICROSECONDS)
    time_elements_object._CopyFromDateTimeValues(date_time_values)
    self.assertEqual(
      time_elements_object.fraction_of_second, decimal.Decimal('0.1234'))

  def testCopyFromDatetime(self):
    """Tests the CopyFromDatetime function."""
    datetime_object = datetime.datetime(2010, 8, 12, 21, 6, 31, 546875)
    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191
    expected_fraction_of_second = decimal.Decimal('0.54')

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
      precision=definitions.PRECISION_10_MILLISECONDS)
    time_elements_object.CopyFromDatetime(datetime_object)

    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.fraction_of_second, expected_fraction_of_second)
    self.assertTrue(time_elements_object.is_local_time)

    datetime_object = datetime.datetime(
        2010, 8, 12, 21, 6, 31, 546875, tzinfo=datetime.timezone.utc)
    time_elements_object.CopyFromDatetime(datetime_object)
    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.fraction_of_second, expected_fraction_of_second)
    self.assertFalse(time_elements_object.is_local_time)

  def testCopyFromStringTuple(self):
    """Tests the CopyFromStringTuple function."""
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        precision=definitions.PRECISION_10_MILLISECONDS)

    expected_time_elements_tuple = (2010, 8, 12, 20, 6, 31)
    expected_fraction_of_second = decimal.Decimal('0.46')
    time_elements_object.CopyFromStringTuple(
        time_elements_tuple=('2010', '8', '12', '20', '6', '31', '0.46'))

    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(
        time_elements_object.fraction_of_second, expected_fraction_of_second)

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        precision=definitions.PRECISION_100_MICROSECONDS)
    time_elements_object.CopyFromStringTuple(
        time_elements_tuple=('2010', '8', '12', '20', '6', '31', '0.4671'))
    self.assertEqual(
        time_elements_object.fraction_of_second, decimal.Decimal('0.4671'))

    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', '96'))

  def testCopyToDateTimeString(self):
    """Tests the CopyToDateTimeString function."""
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.87'),
        precision=definitions.PRECISION_10_MILLISECONDS,
        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.87')

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.874'),
        precision=definitions.PRECISION_1_MILLISECOND,
        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.874')

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.8741'),
        precision=definitions.PRECISION_100_MICROSECONDS,
        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.8741')

  def testNewFromDeltaAndDate(self):
    """Tests the NewFromDeltaAndDate function."""
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.87'),
        is_delta=True,
        precision=definitions.PRECISION_10_MILLISECONDS,
        time_elements_tuple=(1, 0, 0, 20, 6, 31))

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.month, 1)
    self.assertEqual(new_time_elements_object.day_of_month, 12)
    self.assertEqual(
        new_time_elements_object.fraction_of_second, decimal.Decimal('0.87'))

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        time_elements_tuple=(1, 0, 0, 20, 6, 31))

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndDate(2009, 1, 12)

    time_elements_object = time_elements.TimeElementsWithFractionOfSecond()

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndDate(2009, 1, 12)

  def testNewFromDeltaAndYear(self):
    """Tests the NewFromDeltaAndYear function."""
    time_elements_object = time_elements.TimeElementsWithFractionOfSecond(
        fraction_of_second=decimal.Decimal('0.87'),
        is_delta=True,
        precision=definitions.PRECISION_10_MILLISECONDS,
        time_elements_tuple=(1, 8, 12, 20, 6, 31))

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)


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))

  def testGetNormalizedTimestamp(self):
    """Tests the _GetNormalizedTimestamp function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281643591.429'))

    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429), time_zone_offset=60)

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991.429'))

    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))
    time_elements_object.time_zone_offset = 60

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991.429'))

    time_elements_object = time_elements.TimeElementsInMilliseconds()

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertIsNone(normalized_timestamp)

  # TODO: add tests for _CopyFromDateTimeValues

  def testCopyFromDatetime(self):
    """Tests the CopyFromDatetime function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds()

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    datetime_object = datetime.datetime(2010, 8, 12, 21, 6, 31, 546875)
    time_elements_object.CopyFromDatetime(datetime_object)
    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)
    self.assertTrue(time_elements_object.is_local_time)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    datetime_object = datetime.datetime(
        2010, 8, 12, 21, 6, 31, 546875, tzinfo=datetime.timezone.utc)
    time_elements_object.CopyFromDatetime(datetime_object)
    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)
    self.assertFalse(time_elements_object.is_local_time)

  def testCopyFromDateTimeString(self):
    """Tests the CopyFromDateTimeString function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0)
    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, -11644387200)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

  def testCopyFromStringISO8601(self):
    """Tests the CopyFromStringISO8601 function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 500)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.milliseconds, 546)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0)
    time_elements_object.CopyFromStringISO8601(
        '2012-03-05T20:40:00.0000000+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1330980000)
    self.assertEqual(time_elements_object.milliseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    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 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 testCopyToDateTimeStringISO8601(self):
    """Tests the CopyToDateTimeStringISO8601 function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31.429+00:00')

  def testCopyToPosixTimestamp(self):
    """Tests the CopyToPosixTimestamp function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertEqual(posix_timestamp, 1281643591)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertIsNone(posix_timestamp)

  def testCopyToPosixTimestampWithFractionOfSecond(self):
    """Tests the CopyToPosixTimestampWithFractionOfSecond function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertEqual(posix_timestamp, 1281643591)
    self.assertEqual(fraction_of_second, 429)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertIsNone(posix_timestamp)
    self.assertIsNone(fraction_of_second)

  def testGetDate(self):
    """Tests the GetDate function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (2010, 8, 12))

    time_elements_object = time_elements.TimeElementsInMilliseconds()

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (None, None, None))

  def testGetDateWithTimeOfDay(self):
    """Tests the GetDateWithTimeOfDay function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(date_with_time_of_day_tuple, (2010, 8, 12, 20, 6, 31))

    time_elements_object = time_elements.TimeElementsInMilliseconds()

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(
        date_with_time_of_day_tuple, (None, None, None, None, None, None))

  def testGetTimeOfDay(self):
    """Tests the GetTimeOfDay function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429))

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (20, 6, 31))

    time_elements_object = time_elements.TimeElementsInMilliseconds()

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (None, None, None))

  def testNewFromDeltaAndDate(self):
    """Tests the NewFromDeltaAndDate function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        is_delta=True, time_elements_tuple=(1, 0, 0, 20, 6, 31, 429))

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.month, 1)
    self.assertEqual(new_time_elements_object.day_of_month, 12)
    self.assertEqual(new_time_elements_object.milliseconds, 429)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndDate(2009, 1, 12)

  def testNewFromDeltaAndYear(self):
    """Tests the NewFromDeltaAndYear function."""
    time_elements_object = time_elements.TimeElementsInMilliseconds(
        is_delta=True, time_elements_tuple=(1, 8, 12, 20, 6, 31, 429))

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.milliseconds, 429)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndYear(2009)


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, 546875))
    self.assertIsNotNone(time_elements_object)
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object.microseconds, 546875)

    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))

  def testGetNormalizedTimestamp(self):
    """Tests the _GetNormalizedTimestamp function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281643591.429876'))

    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876),
        time_zone_offset=60)

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991.429876'))

    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))
    time_elements_object.time_zone_offset = 60

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(normalized_timestamp, decimal.Decimal('1281639991.429876'))

    time_elements_object = time_elements.TimeElementsInMicroseconds()

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertIsNone(normalized_timestamp)

  # TODO: add tests for _CopyFromDateTimeValues

  def testCopyFromDatetime(self):
    """Tests the CopyFromDatetime function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds()

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    datetime_object = datetime.datetime(2010, 8, 12, 21, 6, 31, 546875)
    time_elements_object.CopyFromDatetime(datetime_object)
    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)
    self.assertTrue(time_elements_object.is_local_time)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    datetime_object = datetime.datetime(
        2010, 8, 12, 21, 6, 31, 546875, tzinfo=datetime.timezone.utc)
    time_elements_object.CopyFromDatetime(datetime_object)
    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)
    self.assertFalse(time_elements_object.is_local_time)

  def testCopyFromDateTimeString(self):
    """Tests the CopyFromDateTimeString function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0)
    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, -11644387200)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

  def testCopyFromStringISO8601(self):
    """Tests the CopyFromStringISO8601 function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 500000)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.microseconds, 546875)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0)
    time_elements_object.CopyFromStringISO8601(
        '2012-03-05T20:40:00.0000000+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1330980000)
    self.assertEqual(time_elements_object.microseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    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 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 testCopyToDateTimeStringISO8601(self):
    """Tests the CopyToDateTimeStringISO8601 function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31.429876+00:00')

  def testCopyToPosixTimestamp(self):
    """Tests the CopyToPosixTimestamp function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertEqual(posix_timestamp, 1281643591)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertIsNone(posix_timestamp)

  def testCopyToPosixTimestampWithFractionOfSecond(self):
    """Tests the CopyToPosixTimestampWithFractionOfSecond function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertEqual(posix_timestamp, 1281643591)
    self.assertEqual(fraction_of_second, 429876)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertIsNone(posix_timestamp)
    self.assertIsNone(fraction_of_second)

  def testGetDate(self):
    """Tests the GetDate function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (2010, 8, 12))

    time_elements_object = time_elements.TimeElementsInMicroseconds()

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (None, None, None))

  def testGetDateWithTimeOfDay(self):
    """Tests the GetDateWithTimeOfDay function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(date_with_time_of_day_tuple, (2010, 8, 12, 20, 6, 31))

    time_elements_object = time_elements.TimeElementsInMicroseconds()

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(
        date_with_time_of_day_tuple, (None, None, None, None, None, None))

  def testGetTimeOfDay(self):
    """Tests the GetTimeOfDay function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876))

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (20, 6, 31))

    time_elements_object = time_elements.TimeElementsInMicroseconds()

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (None, None, None))

  def testNewFromDeltaAndDate(self):
    """Tests the NewFromDeltaAndDate function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        is_delta=True, time_elements_tuple=(1, 0, 0, 20, 6, 31, 429876))

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.month, 1)
    self.assertEqual(new_time_elements_object.day_of_month, 12)
    self.assertEqual(new_time_elements_object.microseconds, 429876)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndDate(2009, 1, 12)

  def testNewFromDeltaAndYear(self):
    """Tests the NewFromDeltaAndYear function."""
    time_elements_object = time_elements.TimeElementsInMicroseconds(
        is_delta=True, time_elements_tuple=(1, 8, 12, 20, 6, 31, 429876))

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.microseconds, 429876)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndYear(2009)


class TimeElementsInNanosecondsTest(unittest.TestCase):
  """Tests for the time elements in nanoseconds."""

  # 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.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 546875218))
    self.assertIsNotNone(time_elements_object)
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)

    with self.assertRaises(ValueError):
      time_elements.TimeElementsInNanoseconds(
          time_elements_tuple=(2010, 13, 12, 20, 6, 31))

    with self.assertRaises(ValueError):
      time_elements.TimeElementsInNanoseconds(
          time_elements_tuple=(2010, 13, 12, 20, 6, 31, 1001))

  def testGetNormalizedTimestamp(self):
    """Tests the _GetNormalizedTimestamp function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(
        normalized_timestamp, decimal.Decimal('1281643591.429876301'))

    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301),
        time_zone_offset=60)

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(
        normalized_timestamp, decimal.Decimal('1281639991.429876301'))

    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))
    time_elements_object.time_zone_offset = 60

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertEqual(
        normalized_timestamp, decimal.Decimal('1281639991.429876301'))

    time_elements_object = time_elements.TimeElementsInNanoseconds()

    normalized_timestamp = time_elements_object._GetNormalizedTimestamp()
    self.assertIsNone(normalized_timestamp)

  # TODO: add tests for _CopyFromDateTimeValues

  def testCopyFromDatetime(self):
    """Tests the CopyFromDatetime function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds()

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    # Note that datetime has microsecond precision.
    datetime_object = datetime.datetime(2010, 8, 12, 21, 6, 31, 546875)
    time_elements_object.CopyFromDatetime(datetime_object)
    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.nanoseconds, 546875000)
    self.assertTrue(time_elements_object.is_local_time)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    expected_number_of_seconds = 1281647191

    # Note that datetime has microsecond precision.
    datetime_object = datetime.datetime(
        2010, 8, 12, 21, 6, 31, 546875, tzinfo=datetime.timezone.utc)
    time_elements_object.CopyFromDatetime(datetime_object)
    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.nanoseconds, 546875000)
    self.assertFalse(time_elements_object.is_local_time)

  def testCopyFromDateTimeString(self):
    """Tests the CopyFromDateTimeString function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromDateTimeString('2010-08-12 21:06:31.546875218')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromDateTimeString(
        '2010-08-12 21:06:31.546875218-01:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromDateTimeString(
        '2010-08-12 21:06:31.546875218+01:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (1601, 1, 2, 0, 0, 0)
    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, -11644387200)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

  def testCopyFromStringISO8601(self):
    """Tests the CopyFromStringISO8601 function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds()

    expected_time_elements_tuple = (2010, 8, 12, 0, 0, 0)
    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, 1281571200)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    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, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 500000000)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31.546875218')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601('2010-08-12T21:06:31,546875218')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, None)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601(
        '2010-08-12T21:06:31.546875218-01:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, -60)

    expected_time_elements_tuple = (2010, 8, 12, 21, 6, 31)
    time_elements_object.CopyFromStringISO8601(
        '2010-08-12T21:06:31.546875218+01:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1281647191)
    self.assertEqual(time_elements_object.nanoseconds, 546875218)
    self.assertEqual(time_elements_object._time_zone_offset, 60)

    expected_time_elements_tuple = (2012, 3, 5, 20, 40, 0)
    time_elements_object.CopyFromStringISO8601(
        '2012-03-05T20:40:00.0000000+00:00')
    self.assertEqual(
        time_elements_object._time_elements_tuple, expected_time_elements_tuple)
    self.assertEqual(time_elements_object._number_of_seconds, 1330980000)
    self.assertEqual(time_elements_object.nanoseconds, 0)
    self.assertEqual(time_elements_object._time_zone_offset, 0)

    with self.assertRaises(ValueError):
      time_elements_object.CopyFromStringISO8601(None)

    with self.assertRaises(ValueError):
      time_elements_object.CopyFromStringISO8601(
          '2010-08-12 21:06:31.546875218+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.TimeElementsInNanoseconds()

    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.nanoseconds, 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 testCopyToDateTimeString(self):
    """Tests the CopyToDateTimeString function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    date_time_string = time_elements_object.CopyToDateTimeString()
    self.assertEqual(date_time_string, '2010-08-12 20:06:31.429876301')

    time_elements_object = time_elements.TimeElementsInNanoseconds()

    date_time_string = time_elements_object.CopyToDateTimeString()
    self.assertIsNone(date_time_string)

  def testCopyToDateTimeStringISO8601(self):
    """Tests the CopyToDateTimeStringISO8601 function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    date_time_string = time_elements_object.CopyToDateTimeStringISO8601()
    self.assertEqual(date_time_string, '2010-08-12T20:06:31.429876301+00:00')

  def testCopyToPosixTimestamp(self):
    """Tests the CopyToPosixTimestamp function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertEqual(posix_timestamp, 1281643591)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp = time_elements_object.CopyToPosixTimestamp()
    self.assertIsNone(posix_timestamp)

  def testCopyToPosixTimestampWithFractionOfSecond(self):
    """Tests the CopyToPosixTimestampWithFractionOfSecond function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertEqual(posix_timestamp, 1281643591)
    self.assertEqual(fraction_of_second, 429876301)

    time_elements_object = time_elements.TimeElements()

    posix_timestamp, fraction_of_second = (
        time_elements_object.CopyToPosixTimestampWithFractionOfSecond())
    self.assertIsNone(posix_timestamp)
    self.assertIsNone(fraction_of_second)

  def testGetDate(self):
    """Tests the GetDate function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (2010, 8, 12))

    time_elements_object = time_elements.TimeElementsInNanoseconds()

    date_tuple = time_elements_object.GetDate()
    self.assertEqual(date_tuple, (None, None, None))

  def testGetDateWithTimeOfDay(self):
    """Tests the GetDateWithTimeOfDay function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(date_with_time_of_day_tuple, (2010, 8, 12, 20, 6, 31))

    time_elements_object = time_elements.TimeElementsInNanoseconds()

    date_with_time_of_day_tuple = time_elements_object.GetDateWithTimeOfDay()
    self.assertEqual(
        date_with_time_of_day_tuple, (None, None, None, None, None, None))

  def testGetTimeOfDay(self):
    """Tests the GetTimeOfDay function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        time_elements_tuple=(2010, 8, 12, 20, 6, 31, 429876301))

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (20, 6, 31))

    time_elements_object = time_elements.TimeElementsInNanoseconds()

    time_of_day_tuple = time_elements_object.GetTimeOfDay()
    self.assertEqual(time_of_day_tuple, (None, None, None))

  def testNewFromDeltaAndDate(self):
    """Tests the NewFromDeltaAndDate function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        is_delta=True, time_elements_tuple=(1, 0, 0, 20, 6, 31, 429876301))

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.month, 1)
    self.assertEqual(new_time_elements_object.day_of_month, 12)
    self.assertEqual(new_time_elements_object.nanoseconds, 429876301)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndDate(
        2009, 1, 12)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndDate(2009, 1, 12)

  def testNewFromDeltaAndYear(self):
    """Tests the NewFromDeltaAndYear function."""
    time_elements_object = time_elements.TimeElementsInNanoseconds(
        is_delta=True, time_elements_tuple=(1, 8, 12, 20, 6, 31, 429876301))

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNotNone(new_time_elements_object)
    self.assertFalse(new_time_elements_object.is_delta)
    self.assertEqual(new_time_elements_object.year, 2010)
    self.assertEqual(new_time_elements_object.nanoseconds, 429876301)

    time_elements_object = time_elements.TimeElements(is_delta=True)

    new_time_elements_object = time_elements_object.NewFromDeltaAndYear(2009)
    self.assertIsNone(new_time_elements_object)

    time_elements_object = time_elements.TimeElements(is_delta=False)

    with self.assertRaises(ValueError):
      time_elements_object.NewFromDeltaAndYear(2009)


if __name__ == '__main__':
  unittest.main()
