blob: 1e014ff4836751936ec56365c616ca46d9fb6882 [file] [log] [blame]
Dan Shidfea3682014-08-10 23:38:40 -07001# 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 time
9
Benny Peaked322d3d2017-02-08 15:39:28 -080010from autotest_lib.client.common_lib import decorators
11
Paul Hobbs74a56112017-11-03 19:33:37 +000012
Benny Peaked322d3d2017-02-08 15:39:28 -080013try:
14 import pytz
15except ImportError:
16 pytz = None
Benny Peaked322d3d2017-02-08 15:39:28 -080017
Paul Hobbs74a56112017-11-03 19:33:37 +000018
Benny Peaked322d3d2017-02-08 15:39:28 -080019try:
20 import tzlocal
21except ImportError:
22 tzlocal = None
Benny Peaked322d3d2017-02-08 15:39:28 -080023
Dan Shidfea3682014-08-10 23:38:40 -070024
25# This format is used to parse datetime value in MySQL database and should not
26# be modified.
27TIME_FMT = '%Y-%m-%d %H:%M:%S'
MK Ryu0c1a37d2015-04-30 12:00:55 -070028TIME_FMT_MICRO = '%Y-%m-%d %H:%M:%S.%f'
Dan Shidfea3682014-08-10 23:38:40 -070029
30def time_string_to_datetime(time_string, handle_type_error=False):
31 """Convert a string of time to a datetime object.
32
MK Ryu0c1a37d2015-04-30 12:00:55 -070033 The format of date string must match '%Y-%m-%d %H:%M:%S' or
34 '%Y-%m-%d %H:%M:%S.%f'.
Dan Shidfea3682014-08-10 23:38:40 -070035
36 @param time_string: String of date, e.g., 2014-12-05 15:32:45
MK Ryu0c1a37d2015-04-30 12:00:55 -070037 @param handle_type_error: Set to True to prevent the method raise
38 TypeError if given time_string is corrupted. Default is False.
39
Dan Shidfea3682014-08-10 23:38:40 -070040 @return: A datetime object with time of the given date string.
MK Ryu0c1a37d2015-04-30 12:00:55 -070041
Dan Shidfea3682014-08-10 23:38:40 -070042 """
43 try:
MK Ryu0c1a37d2015-04-30 12:00:55 -070044 try:
45 return datetime.datetime.strptime(time_string, TIME_FMT)
46 except ValueError:
47 return datetime.datetime.strptime(time_string, TIME_FMT_MICRO)
Dan Shidfea3682014-08-10 23:38:40 -070048 except TypeError:
49 if handle_type_error:
50 return None
51 else:
52 raise
53
54
J. Richard Barnettec9b79332014-09-22 13:14:33 -070055def date_string_to_epoch_time(date_string):
56 """Parse a date time string into seconds since the epoch.
Dan Shidfea3682014-08-10 23:38:40 -070057
MK Ryuc9c0c3f2014-10-27 14:36:01 -070058 @param date_string: A string, formatted according to `TIME_FMT`.
J. Richard Barnettec9b79332014-09-22 13:14:33 -070059
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
Prashanth Balasubramanianbaabef22014-11-04 12:38:44 -080066def epoch_time_to_date_string(epoch_time, fmt_string=TIME_FMT):
J. Richard Barnettec9b79332014-09-22 13:14:33 -070067 """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.
Prashanth Balasubramanianbaabef22014-11-04 12:38:44 -080071 @param fmt_string: A string describing the format of the datetime
72 string output.
73
Dan Shidfea3682014-08-10 23:38:40 -070074 @returns: string formatted in the following way: "yyyy-mm-dd hh:mm:ss"
75 """
76 if epoch_time:
77 return datetime.datetime.fromtimestamp(
Prashanth Balasubramanianbaabef22014-11-04 12:38:44 -080078 int(epoch_time)).strftime(fmt_string)
Dan Shidfea3682014-08-10 23:38:40 -070079 return None
80
81
82def 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.
MK Ryuc9c0c3f2014-10-27 14:36:01 -070091 @returns: epoch time if value is datetime.datetime,
92 otherwise returns the value.
Dan Shidfea3682014-08-10 23:38:40 -070093 @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):
Dan Shif8b71d12014-09-03 10:31:08 -070098 return time.mktime(value.timetuple()) + 0.000001 * value.microsecond
Dan Shidfea3682014-08-10 23:38:40 -070099 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
Benny Peaked322d3d2017-02-08 15:39:28 -0800103
104
105@decorators.test_module_available(pytz, raise_error=True)
106@decorators.test_module_available(tzlocal, raise_error=True)
107def 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 """
Dan Shi395697d2017-05-15 12:18:41 -0700115 if datetime_val is None:
116 return None
117
Benny Peaked322d3d2017-02-08 15:39:28 -0800118 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)
Brian Norris7b1a83c2017-04-18 17:14:21 -0700121 return (utc_datetime - epoch).total_seconds()