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 7import datetime 8import logging 9import time 10 11from autotest_lib.client.common_lib import decorators 12 13 14try: 15 import pytz 16except ImportError: 17 pytz = None 18 logging.error('Could not import pytz.') 19 20 21try: 22 import tzlocal 23except 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. 30TIME_FMT = '%Y-%m-%d %H:%M:%S' 31TIME_FMT_MICRO = '%Y-%m-%d %H:%M:%S.%f' 32 33def 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 58def 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 69def 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 85def 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) 110def 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()