Robot Framework Integrated Development Environment (RIDE)
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 
305 
306 from __future__ import absolute_import
307 
308 from datetime import datetime, timedelta
309 import time
310 import re
311 
312 from robotide.lib.robot.version import get_version
313 from robotide.lib.robot.utils import (elapsed_time_to_string, is_falsy, is_number,
314  is_string, roundup, secs_to_timestr, timestr_to_secs,
315  type_name, IRONPYTHON)
316 
317 __version__ = get_version()
318 __all__ = ['convert_time', 'convert_date', 'subtract_date_from_date',
319  'subtract_time_from_date', 'subtract_time_from_time',
320  'add_time_to_time', 'add_time_to_date', 'get_current_date']
321 
322 
323 
347 def get_current_date(time_zone='local', increment=0,
348  result_format='timestamp', exclude_millis=False):
349  if time_zone.upper() == 'LOCAL':
350  dt = datetime.now()
351  elif time_zone.upper() == 'UTC':
352  dt = datetime.utcnow()
353  else:
354  raise ValueError("Unsupported timezone '%s'." % time_zone)
355  date = Date(dt) + Time(increment)
356  return date.convert(result_format, millis=is_falsy(exclude_millis))
357 
358 
359 
376 def convert_date(date, result_format='timestamp', exclude_millis=False,
377  date_format=None):
378  return Date(date, date_format).convert(result_format,
379  millis=is_falsy(exclude_millis))
380 
381 
382 
398 def convert_time(time, result_format='number', exclude_millis=False):
399  return Time(time).convert(result_format, millis=is_falsy(exclude_millis))
400 
401 
402 
421 def subtract_date_from_date(date1, date2, result_format='number',
422  exclude_millis=False, date1_format=None,
423  date2_format=None):
424  time = Date(date1, date1_format) - Date(date2, date2_format)
425  return time.convert(result_format, millis=is_falsy(exclude_millis))
426 
427 
428 
446 def add_time_to_date(date, time, result_format='timestamp',
447  exclude_millis=False, date_format=None):
448  date = Date(date, date_format) + Time(time)
449  return date.convert(result_format, millis=is_falsy(exclude_millis))
450 
451 
452 
470 def subtract_time_from_date(date, time, result_format='timestamp',
471  exclude_millis=False, date_format=None):
472  date = Date(date, date_format) - Time(time)
473  return date.convert(result_format, millis=is_falsy(exclude_millis))
474 
475 
476 
491 def add_time_to_time(time1, time2, result_format='number',
492  exclude_millis=False):
493  time = Time(time1) + Time(time2)
494  return time.convert(result_format, millis=is_falsy(exclude_millis))
495 
496 
497 
513 def subtract_time_from_time(time1, time2, result_format='number',
514  exclude_millis=False):
515  time = Time(time1) - Time(time2)
516  return time.convert(result_format, millis=is_falsy(exclude_millis))
517 
518 
519 class Date():
520 
521  def __init__(self, date, input_format=None):
522  self.datetimedatetime = self._convert_to_datetime_convert_to_datetime(date, input_format)
523 
524  @property
525  seconds = property
526 
527  def seconds(self):
528  # Mainly for backwards compatibility with RF 2.9.1 and earlier.
529  return self._convert_to_epoch_convert_to_epoch(self.datetimedatetime)
530 
531  def _convert_to_datetime(self, date, input_format):
532  if isinstance(date, datetime):
533  return date
534  if is_number(date):
535  return self._seconds_to_datetime_seconds_to_datetime(date)
536  if is_string(date):
537  return self._string_to_datetime_string_to_datetime(date, input_format)
538  raise ValueError("Unsupported input '%s'." % date)
539 
540  def _seconds_to_datetime(self, secs):
541  # Workaround microsecond rounding errors with IronPython:
542  # https://github.com/IronLanguages/main/issues/1170
543  # Also Jython had similar problems, but they seem to be fixed in 2.7.
544  dt = datetime.fromtimestamp(secs)
545  return dt.replace(microsecond=roundup(secs % 1 * 1e6))
546 
547  def _string_to_datetime(self, ts, input_format):
548  if not input_format:
549  ts = self._normalize_timestamp_normalize_timestamp(ts)
550  input_format = '%Y-%m-%d %H:%M:%S.%f'
551  if self._need_to_handle_f_directive_need_to_handle_f_directive(input_format):
552  return self._handle_un_supported_f_directive_handle_un_supported_f_directive(ts, input_format)
553  return datetime.strptime(ts, input_format)
554 
555  def _normalize_timestamp(self, date):
556  ts = ''.join(d for d in date if d.isdigit())
557  if not (8 <= len(ts) <= 20):
558  raise ValueError("Invalid timestamp '%s'." % date)
559  ts = ts.ljust(20, '0')
560  return '%s-%s-%s %s:%s:%s.%s' % (ts[:4], ts[4:6], ts[6:8], ts[8:10],
561  ts[10:12], ts[12:14], ts[14:])
562 
563  def _need_to_handle_f_directive(self, format):
564  # https://github.com/IronLanguages/main/issues/1169
565  return IRONPYTHON and '%f' in format
566 
567  def _handle_un_supported_f_directive(self, ts, input_format):
568  input_format = self._remove_f_from_format_remove_f_from_format(input_format)
569  match = re.search('\d+$', ts)
570  if not match:
571  raise ValueError("time data '%s' does not match format '%s%%f'."
572  % (ts, input_format))
573  end_digits = match.group(0)
574  micro = int(end_digits.ljust(6, '0'))
575  dt = datetime.strptime(ts[:-len(end_digits)], input_format)
576  return dt.replace(microsecond=micro)
577 
578  def _remove_f_from_format(self, format):
579  if not format.endswith('%f'):
580  raise ValueError('%f directive is supported only at the end of '
581  'the format string on this Python interpreter.')
582  return format[:-2]
583 
584  def convert(self, format, millis=True):
585  dt = self.datetimedatetime
586  if not millis:
587  secs = 1 if dt.microsecond >= 5e5 else 0
588  dt = dt.replace(microsecond=0) + timedelta(seconds=secs)
589  if '%' in format:
590  return self._convert_to_custom_timestamp_convert_to_custom_timestamp(dt, format)
591  format = format.lower()
592  if format == 'timestamp':
593  return self._convert_to_timestamp_convert_to_timestamp(dt, millis)
594  if format == 'datetime':
595  return dt
596  if format == 'epoch':
597  return self._convert_to_epoch_convert_to_epoch(dt)
598  raise ValueError("Unknown format '%s'." % format)
599 
600  def _convert_to_custom_timestamp(self, dt, format):
601  if not self._need_to_handle_f_directive_need_to_handle_f_directive(format):
602  return dt.strftime(format)
603  format = self._remove_f_from_format_remove_f_from_format(format)
604  return dt.strftime(format) + '%06d' % dt.microsecond
605 
606  def _convert_to_timestamp(self, dt, millis=True):
607  if not millis:
608  return dt.strftime('%Y-%m-%d %H:%M:%S')
609  ms = roundup(dt.microsecond / 1000.0)
610  if ms == 1000:
611  dt += timedelta(seconds=1)
612  ms = 0
613  return dt.strftime('%Y-%m-%d %H:%M:%S') + '.%03d' % ms
614 
615  def _convert_to_epoch(self, dt):
616  return time.mktime(dt.timetuple()) + dt.microsecond / 1e6
617 
618  def __add__(self, other):
619  if isinstance(other, Time):
620  return Date(self.datetimedatetime + other.timedelta)
621  raise TypeError('Can only add Time to Date, got %s.' % type_name(other))
622 
623  def __sub__(self, other):
624  if isinstance(other, Date):
625  return Time(self.datetimedatetime - other.datetime)
626  if isinstance(other, Time):
627  return Date(self.datetimedatetime - other.timedelta)
628  raise TypeError('Can only subtract Date or Time from Date, got %s.'
629  % type_name(other))
630 
631 
632 class Time():
633 
634  def __init__(self, time):
635  self.secondsseconds = float(self._convert_time_to_seconds_convert_time_to_seconds(time))
636 
637  def _convert_time_to_seconds(self, time):
638  if isinstance(time, timedelta):
639  return time.total_seconds()
640  return timestr_to_secs(time, round_to=None)
641 
642  @property
643  timedelta = property
644 
645  def timedelta(self):
646  return timedelta(seconds=self.secondsseconds)
647 
648  def convert(self, format, millis=True):
649  try:
650  result_converter = getattr(self, '_convert_to_%s' % format.lower())
651  except AttributeError:
652  raise ValueError("Unknown format '%s'." % format)
653  seconds = self.secondsseconds if millis else float(roundup(self.secondsseconds))
654  return result_converter(seconds, millis)
655 
656  def _convert_to_number(self, seconds, millis=True):
657  return seconds
658 
659  def _convert_to_verbose(self, seconds, millis=True):
660  return secs_to_timestr(seconds)
661 
662  def _convert_to_compact(self, seconds, millis=True):
663  return secs_to_timestr(seconds, compact=True)
664 
665  def _convert_to_timer(self, seconds, millis=True):
666  return elapsed_time_to_string(seconds * 1000, include_millis=millis)
667 
668  def _convert_to_timedelta(self, seconds, millis=True):
669  return timedelta(seconds=seconds)
670 
671  def __add__(self, other):
672  if isinstance(other, Time):
673  return Time(self.secondsseconds + other.seconds)
674  raise TypeError('Can only add Time to Time, got %s.' % type_name(other))
675 
676  def __sub__(self, other):
677  if isinstance(other, Time):
678  return Time(self.secondsseconds - other.seconds)
679  raise TypeError('Can only subtract Time from Time, got %s.'
680  % type_name(other))
def _convert_to_datetime(self, date, input_format)
Definition: DateTime.py:531
def convert(self, format, millis=True)
Definition: DateTime.py:584
def __init__(self, date, input_format=None)
Definition: DateTime.py:521
def _convert_to_timestamp(self, dt, millis=True)
Definition: DateTime.py:606
def _convert_to_custom_timestamp(self, dt, format)
Definition: DateTime.py:600
def _need_to_handle_f_directive(self, format)
Definition: DateTime.py:563
def _string_to_datetime(self, ts, input_format)
Definition: DateTime.py:547
def _handle_un_supported_f_directive(self, ts, input_format)
Definition: DateTime.py:567
def _convert_to_number(self, seconds, millis=True)
Definition: DateTime.py:656
def _convert_to_timedelta(self, seconds, millis=True)
Definition: DateTime.py:668
def _convert_to_compact(self, seconds, millis=True)
Definition: DateTime.py:662
def _convert_to_timer(self, seconds, millis=True)
Definition: DateTime.py:665
def convert(self, format, millis=True)
Definition: DateTime.py:648
def _convert_to_verbose(self, seconds, millis=True)
Definition: DateTime.py:659
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:447
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:471
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:514
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:492
def convert_time(time, result_format='number', exclude_millis=False)
Converts between supported time formats.
Definition: DateTime.py:398
def convert_date(date, result_format='timestamp', exclude_millis=False, date_format=None)
Converts between supported date formats.
Definition: DateTime.py:377
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:423
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:348
def roundup(number, ndigits=0, return_type=None)
Rounds number to the given number of digits.
Definition: misc.py:34
def elapsed_time_to_string(elapsed, include_millis=True)
Converts elapsed time in milliseconds to format 'hh:mm:ss.mil'.
Definition: robottime.py:335
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
Definition: robottime.py:126
def timestr_to_secs(timestr, round_to=3)
Parses time like '1h 10s', '01:00:10' or '42' and returns seconds.
Definition: robottime.py:45
def is_falsy(item)
Opposite of :func:is_truthy.
Definition: robottypes.py:56
def get_version(naked=False)
Definition: version.py:24