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