Home | History | Annotate | Download | only in common_lib
      1 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 # This module contains some commonly used time conversion function.
      6 
      7 import datetime
      8 import logging
      9 import time
     10 
     11 from autotest_lib.client.common_lib import decorators
     12 
     13 
     14 try:
     15     import pytz
     16 except ImportError:
     17     pytz = None
     18     logging.error('Could not import pytz.')
     19 
     20 
     21 try:
     22     import tzlocal
     23 except ImportError:
     24     tzlocal = None
     25     logging.error('Could not import tzlocal.')
     26 
     27 
     28 # This format is used to parse datetime value in MySQL database and should not
     29 # be modified.
     30 TIME_FMT = '%Y-%m-%d %H:%M:%S'
     31 TIME_FMT_MICRO = '%Y-%m-%d %H:%M:%S.%f'
     32 
     33 def time_string_to_datetime(time_string, handle_type_error=False):
     34     """Convert a string of time to a datetime object.
     35 
     36     The format of date string must match '%Y-%m-%d %H:%M:%S' or
     37     '%Y-%m-%d %H:%M:%S.%f'.
     38 
     39     @param time_string: String of date, e.g., 2014-12-05 15:32:45
     40     @param handle_type_error: Set to True to prevent the method raise
     41             TypeError if given time_string is corrupted. Default is False.
     42 
     43     @return: A datetime object with time of the given date string.
     44 
     45     """
     46     try:
     47         try:
     48             return datetime.datetime.strptime(time_string, TIME_FMT)
     49         except ValueError:
     50             return datetime.datetime.strptime(time_string, TIME_FMT_MICRO)
     51     except TypeError:
     52         if handle_type_error:
     53             return None
     54         else:
     55             raise
     56 
     57 
     58 def date_string_to_epoch_time(date_string):
     59     """Parse a date time string into seconds since the epoch.
     60 
     61     @param date_string: A string, formatted according to `TIME_FMT`.
     62 
     63     @return The number of seconds since the UNIX epoch, as a float.
     64 
     65     """
     66     return time.mktime(time.strptime(date_string, TIME_FMT))
     67 
     68 
     69 def epoch_time_to_date_string(epoch_time, fmt_string=TIME_FMT):
     70     """Convert epoch time (float) to a human readable date string.
     71 
     72     @param epoch_time The number of seconds since the UNIX epoch, as
     73                       a float.
     74     @param fmt_string: A string describing the format of the datetime
     75         string output.
     76 
     77     @returns: string formatted in the following way: "yyyy-mm-dd hh:mm:ss"
     78     """
     79     if epoch_time:
     80         return datetime.datetime.fromtimestamp(
     81                 int(epoch_time)).strftime(fmt_string)
     82     return None
     83 
     84 
     85 def to_epoch_time(value):
     86     """Convert the given value to epoch time.
     87 
     88     Convert the given value to epoch time if it is a datetime object or a string
     89     can be converted to datetime object.
     90     If the given value is a number, this function assume the value is a epoch
     91     time value, and returns the value itself.
     92 
     93     @param value: A datetime object or a number.
     94     @returns: epoch time if value is datetime.datetime,
     95               otherwise returns the value.
     96     @raise ValueError: If value is not a datetime object or a number.
     97     """
     98     if isinstance(value, basestring):
     99         value = time_string_to_datetime(value)
    100     if isinstance(value, datetime.datetime):
    101         return time.mktime(value.timetuple()) + 0.000001 * value.microsecond
    102     if not isinstance(value, int) and not isinstance(value, float):
    103         raise ValueError('Value should be a datetime object, string or a '
    104                          'number. Unexpected value: %s.' % value)
    105     return value
    106 
    107 
    108 @decorators.test_module_available(pytz, raise_error=True)
    109 @decorators.test_module_available(tzlocal, raise_error=True)
    110 def to_utc_timestamp(datetime_val):
    111     """Transforms a datetime object into a utc timestamp.
    112 
    113     @param datetime_val: A datetime timestamp.
    114 
    115     @returns A datetime as a UTC floating point timestamp in seconds since
    116              epoch.
    117     """
    118     epoch = datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)
    119     local_datetime = datetime_val.replace(tzinfo=tzlocal.get_localzone())
    120     utc_datetime = local_datetime.astimezone(tz=pytz.utc)
    121     return (utc_datetime - epoch).total_seconds()