Robot Framework
DateTime.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 
295 
296 from datetime import datetime, timedelta
297 import time
298 
299 from robot.version import get_version
300 from robot.utils import (elapsed_time_to_string, is_falsy, is_number, is_string,
301  secs_to_timestr, timestr_to_secs, type_name)
302 
303 __version__ = get_version()
304 __all__ = ['convert_time', 'convert_date', 'subtract_date_from_date',
305  'subtract_time_from_date', 'subtract_time_from_time',
306  'add_time_to_time', 'add_time_to_date', 'get_current_date']
307 
308 
309 
334 def get_current_date(time_zone='local', increment=0,
335  result_format='timestamp', exclude_millis=False):
336  upper = time_zone.upper()
337  if upper == 'LOCAL':
338  dt = datetime.now()
339  # Epoch time is same regardless the timezone. We convert `dt` to epoch time
340  # using `time.mktime()` afterwards, and it expects time in local time.
341  # For details: https://github.com/robotframework/robotframework/issues/3306
342  elif upper == 'UTC' and result_format.upper() == 'EPOCH':
343  dt = datetime.now()
344  elif upper == 'UTC':
345  dt = datetime.utcnow()
346  else:
347  raise ValueError("Unsupported timezone '%s'." % time_zone)
348  date = Date(dt) + Time(increment)
349  return date.convert(result_format, millis=is_falsy(exclude_millis))
350 
351 
352 
369 def convert_date(date, result_format='timestamp', exclude_millis=False,
370  date_format=None):
371  return Date(date, date_format).convert(result_format,
372  millis=is_falsy(exclude_millis))
373 
374 
375 
391 def convert_time(time, result_format='number', exclude_millis=False):
392  return Time(time).convert(result_format, millis=is_falsy(exclude_millis))
393 
394 
395 
414 def subtract_date_from_date(date1, date2, result_format='number',
415  exclude_millis=False, date1_format=None,
416  date2_format=None):
417  time = Date(date1, date1_format) - Date(date2, date2_format)
418  return time.convert(result_format, millis=is_falsy(exclude_millis))
419 
420 
421 
439 def add_time_to_date(date, time, result_format='timestamp',
440  exclude_millis=False, date_format=None):
441  date = Date(date, date_format) + Time(time)
442  return date.convert(result_format, millis=is_falsy(exclude_millis))
443 
444 
445 
463 def subtract_time_from_date(date, time, result_format='timestamp',
464  exclude_millis=False, date_format=None):
465  date = Date(date, date_format) - Time(time)
466  return date.convert(result_format, millis=is_falsy(exclude_millis))
467 
468 
469 
484 def add_time_to_time(time1, time2, result_format='number',
485  exclude_millis=False):
486  time = Time(time1) + Time(time2)
487  return time.convert(result_format, millis=is_falsy(exclude_millis))
488 
489 
490 
506 def subtract_time_from_time(time1, time2, result_format='number',
507  exclude_millis=False):
508  time = Time(time1) - Time(time2)
509  return time.convert(result_format, millis=is_falsy(exclude_millis))
510 
511 
512 class Date:
513 
514  def __init__(self, date, input_format=None):
515  self.datetimedatetime = self._convert_to_datetime_convert_to_datetime(date, input_format)
516 
517  @property
518  seconds = property
519 
520  def seconds(self):
521  # Mainly for backwards compatibility with RF 2.9.1 and earlier.
522  return self._convert_to_epoch_convert_to_epoch(self.datetimedatetime)
523 
524  def _convert_to_datetime(self, date, input_format):
525  if isinstance(date, datetime):
526  return date
527  if is_number(date):
528  return datetime.fromtimestamp(date)
529  if is_string(date):
530  return self._string_to_datetime_string_to_datetime(date, input_format)
531  raise ValueError("Unsupported input '%s'." % date)
532 
533  def _string_to_datetime(self, ts, input_format):
534  if not input_format:
535  ts = self._normalize_timestamp_normalize_timestamp(ts)
536  input_format = '%Y-%m-%d %H:%M:%S.%f'
537  return datetime.strptime(ts, input_format)
538 
539  def _normalize_timestamp(self, date):
540  ts = ''.join(d for d in date if d.isdigit())
541  if not (8 <= len(ts) <= 20):
542  raise ValueError("Invalid timestamp '%s'." % date)
543  ts = ts.ljust(20, '0')
544  return '%s-%s-%s %s:%s:%s.%s' % (ts[:4], ts[4:6], ts[6:8], ts[8:10],
545  ts[10:12], ts[12:14], ts[14:])
546 
547  def convert(self, format, millis=True):
548  dt = self.datetimedatetime
549  if not millis:
550  secs = 1 if dt.microsecond >= 5e5 else 0
551  dt = dt.replace(microsecond=0) + timedelta(seconds=secs)
552  if '%' in format:
553  return self._convert_to_custom_timestamp_convert_to_custom_timestamp(dt, format)
554  format = format.lower()
555  if format == 'timestamp':
556  return self._convert_to_timestamp_convert_to_timestamp(dt, millis)
557  if format == 'datetime':
558  return dt
559  if format == 'epoch':
560  return self._convert_to_epoch_convert_to_epoch(dt)
561  raise ValueError("Unknown format '%s'." % format)
562 
563  def _convert_to_custom_timestamp(self, dt, format):
564  return dt.strftime(format)
565 
566  def _convert_to_timestamp(self, dt, millis=True):
567  if not millis:
568  return dt.strftime('%Y-%m-%d %H:%M:%S')
569  ms = round(dt.microsecond / 1000)
570  if ms == 1000:
571  dt += timedelta(seconds=1)
572  ms = 0
573  return dt.strftime('%Y-%m-%d %H:%M:%S') + '.%03d' % ms
574 
575  def _convert_to_epoch(self, dt):
576  return time.mktime(dt.timetuple()) + dt.microsecond / 1e6
577 
578  def __add__(self, other):
579  if isinstance(other, Time):
580  return Date(self.datetimedatetime + other.timedelta)
581  raise TypeError('Can only add Time to Date, got %s.' % type_name(other))
582 
583  def __sub__(self, other):
584  if isinstance(other, Date):
585  return Time(self.datetimedatetime - other.datetime)
586  if isinstance(other, Time):
587  return Date(self.datetimedatetime - other.timedelta)
588  raise TypeError('Can only subtract Date or Time from Date, got %s.'
589  % type_name(other))
590 
591 
592 class Time:
593 
594  def __init__(self, time):
595  self.secondsseconds = float(self._convert_time_to_seconds_convert_time_to_seconds(time))
596 
597  def _convert_time_to_seconds(self, time):
598  if isinstance(time, timedelta):
599  return time.total_seconds()
600  return timestr_to_secs(time, round_to=None)
601 
602  @property
603  timedelta = property
604 
605  def timedelta(self):
606  return timedelta(seconds=self.secondsseconds)
607 
608  def convert(self, format, millis=True):
609  try:
610  result_converter = getattr(self, '_convert_to_%s' % format.lower())
611  except AttributeError:
612  raise ValueError("Unknown format '%s'." % format)
613  seconds = self.secondsseconds if millis else float(round(self.secondsseconds))
614  return result_converter(seconds, millis)
615 
616  def _convert_to_number(self, seconds, millis=True):
617  return seconds
618 
619  def _convert_to_verbose(self, seconds, millis=True):
620  return secs_to_timestr(seconds)
621 
622  def _convert_to_compact(self, seconds, millis=True):
623  return secs_to_timestr(seconds, compact=True)
624 
625  def _convert_to_timer(self, seconds, millis=True):
626  return elapsed_time_to_string(seconds * 1000, include_millis=millis)
627 
628  def _convert_to_timedelta(self, seconds, millis=True):
629  return timedelta(seconds=seconds)
630 
631  def __add__(self, other):
632  if isinstance(other, Time):
633  return Time(self.secondsseconds + other.seconds)
634  raise TypeError('Can only add Time to Time, got %s.' % type_name(other))
635 
636  def __sub__(self, other):
637  if isinstance(other, Time):
638  return Time(self.secondsseconds - other.seconds)
639  raise TypeError('Can only subtract Time from Time, got %s.'
640  % type_name(other))
def __sub__(self, other)
Definition: DateTime.py:583
def _convert_to_epoch(self, dt)
Definition: DateTime.py:575
def _normalize_timestamp(self, date)
Definition: DateTime.py:539
def _string_to_datetime(self, ts, input_format)
Definition: DateTime.py:533
def convert(self, format, millis=True)
Definition: DateTime.py:547
def __add__(self, other)
Definition: DateTime.py:578
def __init__(self, date, input_format=None)
Definition: DateTime.py:514
def _convert_to_datetime(self, date, input_format)
Definition: DateTime.py:524
def _convert_to_custom_timestamp(self, dt, format)
Definition: DateTime.py:563
def _convert_to_timestamp(self, dt, millis=True)
Definition: DateTime.py:566
def __add__(self, other)
Definition: DateTime.py:631
def __sub__(self, other)
Definition: DateTime.py:636
def _convert_time_to_seconds(self, time)
Definition: DateTime.py:597
def _convert_to_number(self, seconds, millis=True)
Definition: DateTime.py:616
def __init__(self, time)
Definition: DateTime.py:594
def _convert_to_verbose(self, seconds, millis=True)
Definition: DateTime.py:619
def _convert_to_compact(self, seconds, millis=True)
Definition: DateTime.py:622
def _convert_to_timer(self, seconds, millis=True)
Definition: DateTime.py:625
def _convert_to_timedelta(self, seconds, millis=True)
Definition: DateTime.py:628
def convert(self, format, millis=True)
Definition: DateTime.py:608
def add_time_to_time(time1, time2, result_format='number', exclude_millis=False)
Adds time to another time and returns the resulting time.
Definition: DateTime.py:485
def subtract_time_from_date(date, time, result_format='timestamp', exclude_millis=False, date_format=None)
Subtracts time from date and returns the resulting date.
Definition: DateTime.py:464
def subtract_time_from_time(time1, time2, result_format='number', exclude_millis=False)
Subtracts time from another time and returns the resulting time.
Definition: DateTime.py:507
def subtract_date_from_date(date1, date2, result_format='number', exclude_millis=False, date1_format=None, date2_format=None)
Subtracts date from another date and returns time between.
Definition: DateTime.py:416
def get_current_date(time_zone='local', increment=0, result_format='timestamp', exclude_millis=False)
Returns current local or UTC time with an optional increment.
Definition: DateTime.py:335
def convert_time(time, result_format='number', exclude_millis=False)
Converts between supported time formats.
Definition: DateTime.py:391
def convert_date(date, result_format='timestamp', exclude_millis=False, date_format=None)
Converts between supported date formats.
Definition: DateTime.py:370
def add_time_to_date(date, time, result_format='timestamp', exclude_millis=False, date_format=None)
Adds time to date and returns the resulting date.
Definition: DateTime.py:440
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
Definition: robottime.py:151
def timestr_to_secs(timestr, round_to=3, accept_plain_values=True)
Parses time strings like '1h 10s', '01:00:10' and '42' and returns seconds.
Definition: robottime.py:55
def elapsed_time_to_string(elapsed, include_millis=True)
Converts elapsed time in milliseconds to format 'hh:mm:ss.mil'.
Definition: robottime.py:374
def is_falsy(item)
Opposite of :func:is_truthy.
Definition: robottypes.py:169
def type_name(item, capitalize=False)
Return "non-technical" type name for objects and types.
Definition: robottypes.py:86
def get_version(naked=False)
Definition: version.py:24