This topic explains how to work with date values in Python and provides examples of date operations. It contains the following sections:
When writing scripts we often deal with dates. There are certain date value formats and TestComplete routines that help handle dates.
Since the TestComplete scripting engine only supports OLE-compatible data types, the date-time values are implemented as floating-point variant values in a special format. The integer part of this value represents the number of days that have passed since December 30, 1899. The number after the decimal separator represents the fraction of a 24-hour period that has elapsed. However, you do not have to understand what these floating-point values represent. TestComplete provides several routines that help you convert these values to their string representation (see below).
Below are some examples of date-time values and their meaning:
|0.25||December 30, 1899. 6:00 AM|
|36345.5||July 4, 1999. 12:00 PM|
|39094.65625||January 12, 2007. 3:45 PM|
When you are only working with date values the fractional part can be omitted.
Objects and Functions for Working With Date Values
TestComplete has the
aqDateTime object that contains methods that can be useful when operating with dates.
|AddDays||Adds or subtracts the specified number of days to (from) the given date.|
|AddMonths||Adds or subtracts the specified number of months to (from) the given date.|
|AddTime||Adds or subtracts the specified number of days, hours, minutes and seconds to (from) the given date.|
|Compare||Compares two specified date/time values.|
|GetDay||Returns the ordinal number of a day in a month.|
|GetDayOfWeek||Returns the day of the week for the specified date.|
|GetDayOfYear||Returns the ordinal number of a day in a year.|
|GetMonth||Returns the month number of the specified date.|
|GetYear||Returns the year number of the specified date.|
|IsLeapYear||Indicates whether the specified year is a leap year.|
|Now||Returns the current date and time.|
|SetDateElements||Returns the Date variable having the specified year, month and day.|
|SetDateTimeElements||Returns the Date variable having the specified date and time portions.|
|SetSystemDateTime||Assigns the specified date and time as the system date and time.|
|Today||Returns the current date.|
One more object,
aqConvert, provides methods to convert strings between date values and their string equivalents:
|DateTimeToFormatStr||Converts the given date value to a string using the specified format.|
|DateTimeToStr||Converts the given date value to a string.|
|StrToDate||Converts the specified string to a date value.|
|StrToDateTime||Converts the specified string to a date/time value.|
aqConvert objects are available for all supported scripting languages, so that you can use them to operate with date values regardless of the chosen language.
Getting Current Date
There are two routines that return the current date:
Now. The difference between them is that the value returned by the
Now routine includes both the date and time parts, whereas the
Date routine returns only the date part. The script below demonstrates how to use them.
def GetDate(): # Obtain the current date TodayValue = aqDateTime.Today() # Obtain the current date and time NowValue = aqDateTime.Now() # Convert the returned date/time values to the string values StringTodayValue = aqConvert.DateTimeToStr(TodayValue) StringNowValue = aqConvert.DateTimeToStr(NowValue) # Post the converted values to the log Log.Message("The date obtained from the Today routine is " + StringTodayValue) Log.Message("The date obtained from the Now routine is " + StringNowValue) # Convert the floating-point values to the string values VariantTodayValue = aqConvert.FloatToStr(TodayValue) VariantNowValue = aqConvert.FloatToStr(NowValue) # Post the converted values to the log Log.Message("The variant representation of TodayValue is " + VariantTodayValue) Log.Message("The variant representation of NowValue is " + VariantNowValue)
Getting Tomorrow’s and Yesterday’s Dates
The sample below demonstrates how the
aqDateTime object can be used to calculate
tomorrow's date. The current date is obtained via the
aqDateTime.Today method. Then the current date value is incremented via the
DateTimeToStr method of the
aqConvert object is used to convert the date value to a string that is posted to the TestComplete log.
def TomorrowDate(): # Obtain the current date CurrentDate = aqDateTime.Today() # Convert the date/time value to a string and post it to the log Today = aqConvert.DateTimeToStr(CurrentDate) Log.Message("Today is " + Today) # Calculate the tomorrow's date, convert the returned date to a string and post this string to the log Tomorrow = aqDateTime.AddDays(CurrentDate, 1) ConvertedTomorrowDate = aqConvert.DateTimeToStr(Tomorrow) Log.Message("Tomorrow will be " + ConvertedTomorrowDate) return Tomorrow
Similarly, you can calculate any date that differs from the current day by a certain amount of days: yesterday, the next or previous week and so on. For example, to get yesterday’s date, you have to pass -1 as the second parameter of the
def YesterdayDate(): # Obtain the current date CurrentDate = aqDateTime.Today() # Convert the date/time value to a string and post it to the log Today = aqConvert.DateTimeToStr(CurrentDate) Log.Message("Today is " + Today) # Calculate the yesterday's date, convert the returned date to a string and post this string to the log YesterdayDate = aqDateTime.AddDays(CurrentDate, -1) ConvertedYesterdayDate = aqConvert.DateTimeToStr(YesterdayDate) Log.Message("Yesterday was " + ConvertedYesterdayDate)
Calculating the Year and Month Duration
Generally, there are 365 days in a calendar year. However, the length of an astronomical year is about 365.242375 days, so, in the course of time, the fractional part would result in an extra day and the calendar year would lag from the astronomical year. To avoid this, the leap year that is 366 days long was invented.
The Gregorian calendar is the current standard calendar in most of the world and it adds a 29th day to February in all years evenly divisible by 4, except for centennial years (those ending in -00), which only receive the extra day if they are evenly divisible by 400. The
aqDateTime object has a special method,
IsLeapYear, that accepts the year number and returns True if the specified year is a leap year. You can use this method to get the exact number of days in the desired year:
def DaysInYear(YearNo): return 365 + aqDateTime.IsLeapYear(YearNo)
In the example above, a Boolean value was added to an integer, since in Python, Booleans have a numerical value of 0 (False) or 1 (True).
IsLeapYear method, you can get the number of days in the month. For all months, except for February, the duration of a month is fixed and is either 30 or 31 days. The duration of February is either 28 or 29 days, depending on whether the current year is a leap year or not. The routine that gets the month duration would be the following:
def DaysInMonth(MonthNo, YearNo): if MonthNo == 1 or MonthNo == 3 or MonthNo == 5 or MonthNo == 7 or MonthNo == 8 or MonthNo == 10 or MonthNo == 12: return 31 elif MonthNo == 2: if aqDateTime.IsLeapYear(YearNo): return 29 else: return 28 elif MonthNo == 4 or MonthNo == 6 or MonthNo == 9 or MonthNo == 11: return 30
To compare date/time values, use the
aqDateTime.Compare method rather than comparison operators (like ==, >, <, != and others) provided by the scripting engine:
def compare(DateTime1, DateTime2): r = aqDateTime.Compare(DateTime1, DateTime2) if r > 0: # DateTime1 > DateTime2 ... else: if r < 0: # DateTime1 < DateTime2 ... else: # DateTime1 == DateTime2 ...
This note does not concern the
Date objects provided by the Python engine. To compare
Date objects, use the features provided by the engine.
Encoding and Decoding Date Values
Since date values are represented as variants, special routines are required for converting a variant value to a calendar date and vice versa. These operations are performed by the SetDateElements, GetYear, GetMonth and GetDay methods of the
aqDateTime object. These methods take into account whether the current year is a leap year and the number of days in a month so that the resulting value is guaranteed to be valid. The
SetDateElements method accepts the parts of a date and returns a variant date value.
def EncodeDateDemo(): # Create a Date variable having the specified year, month and day values myDate = aqDateTime.SetDateElements(2005, 12, 25) # Convert the value of the myDate variable to a string using the specified format and post this string to the log EncodedDate = aqConvert.DateTimeToFormatStr(myDate,"%B/%#d/%Y") Log.Message("The encoded date is "+ EncodedDate) # Convert the value of the myDate variable to a variant value and post it to the log VariantDate = aqConvert.IntToStr(myDate) Log.Message("The variant representation of it is "+ VariantDate)
GetDay methods accept the variant date-time value and return the respective date parts of that value. Below is an example of how to use these routines:
def DecodeDateDemo(): # Obtain the current date CurrentDate = aqDateTime.Today() # Return the parts of the current date value and then post them to the log Year = aqDateTime.GetYear(CurrentDate) Month = aqDateTime.GetMonth(CurrentDate) Day = aqDateTime.GetDay(CurrentDate) Log.Message(str(Day) + " day(s) have passed since the beginning of the " + str(Month) + " month of " + str(Year) + " year.")
Modifying Date Values
Despite the fact that date-time values are represented as floating-point numbers, you cannot explicitly use ordinary arithmetic operators to change dates or times. However, the
aqDateTime scripting object provides a number of methods that were especially designed to modify date-time values. These methods are:
AddTime method allows you to modify the date and time portions at once.
As you may notice from the Getting Tomorrow’s and Yesterday’s Dates section, these methods are used both for incrementing and decrementing date-time values. When a positive number is passed as Month, Days or another parameter, then the resulting value is increased. If the parameter is negative, then the resulting value is decreased.
These methods take into account the number of days in the month, whether the year is a leap year and other aspects of time calculations, which guarantees that the resulting value will be valid.
The code below demonstrates how to use these methods:
def ModifyDates(): Date = aqDateTime.SetDateElements(2007, 1, 25) # Increase the date by 7 days # Note the month changing AlteredDate = aqDateTime.AddDays(Date, 7) Log.Message("Initial date: " + aqConvert.DateTimeToStr(Date)) Log.Message("Altered date 1: " + aqConvert.DateTimeToStr(AlteredDate)) # Increase the date by one month # Note that 28 days were added since the month is February AlteredDate = aqDateTime.AddMonths(AlteredDate, 1) Log.Message("Altered date 2: " + aqConvert.DateTimeToStr(AlteredDate)) # Decrease the date by 1 day AlteredDate = aqDateTime.AddTime(AlteredDate, -1, 0, 0, 0) Log.Message("Altered date 3: " + aqConvert.DateTimeToStr(AlteredDate))
Dealing With Week Days
Besides recognizing a date, month and year, you may need to know which day of the week a certain date falls on. The
aqDateTime.GetDayOfWeek method performs this task. It accepts a variant date and returns the number of the week day that corresponds to it. The returned number ranges between 1 and 7, where 1 corresponds to Sunday, 2 - to Monday, and so on. The sample code below obtains the current date, calculates the day of the week and posts the name of the day to the log.
def DayOfWeekDemo(): WeekDay = aqDateTime.GetDayOfWeek(aqDateTime.Today()) if WeekDay == 1: DayName = "Sunday" elif WeekDay == 2: DayName = "Monday" elif WeekDay == 3: DayName = "Tuesday" elif WeekDay == 4: DayName = "Wednesday" elif WeekDay == 5: DayName = "Sunday" elif WeekDay == 6: DayName = "Thursday" elif WeekDay == 7: DayName = "Friday" elif WeekDay == 8: DayName = "Saturday" Log.Message("Today is " + DayName)
In addition to the day of the week, you can determine the dates when the week starts and ends. This can be done using the following two routines. Here, the number of a week day is subtracted from the specified date to get the beginning of the week, and to get the end of the week, six days are added to the calculated date.
def StartOfWeek (InputDate): # If the input parameter is omitted then current date is taken if InputDate == None: InputDate = aqDateTime.Today() # Using US week day number return aqDateTime.AddDays(InputDate, - aqDateTime.GetDayOfWeek(InputDate) + 1) # Using ISO week day number # return aqDateTime.AddDays(InputDate, - ISODayOfWeek(InputDate) + 1) def EndOfWeek (InputDate): # If the input parameter is omitted then current date is taken if InputDate == None: InputDate = aqDateTime.Today() # Using US week day number return aqDateTime.AddDays(InputDate, - aqDateTime.GetDayOfWeek(InputDate) + 7) # Using ISO week day number # return aqDateTime.AddDays(InputDate, - ISODayOfWeek(InputDate) + 7)
Since the routines use the
Another frequent operation when dealing with dates is calculating the number of weeks that have passed since the beginning of the year. First, you should clarify what week should be considered as the first week of the year. According to the ISO 8601 standard, the first week of a year is a week with the majority (four or more) of days in the starting year. In our case, it is better to use another definition of the first week: the week with the date January, 4th.
Below is a routine that calculates the week number in compliance with this rule. It accepts the date, determines whether the week is the first one, and then calculates the week number as a difference between the end of specified week and the end of the first week divided by 7..
def WeekNumber(InputDate): YearNo = aqDateTime.GetYear(InputDate) EndOfFirstWeek = EndOfWeek(aqDateTime.SetDateElements(YearNo,1,4)) EndOfCurrentWeek = EndOfWeek(InputDate) return 1 + (aqDateTime.GetDayOfYear(EndOfCurrentWeek) - aqDateTime.GetDayOfYear(EndOfFirstWeek)) / 7
Sometimes, it is useful to know on what day of the week the desired month starts or ends. The routines below return the week day numbers that correspond to the beginning and to the end of the month. They have only one input parameter that specifies the date that belongs to the desired month. If the parameter is missing, then the routines return the results for the current month. These routines calculate the day of the month in a similar way the routines above calculate the number of the week.
def StartOfMonthDay (InputDate): # If the input parameter is omitted then current date is taken if InputDate == None: InputDate = aqDateTime.Today() StartDate = aqDateTime.AddDays(InputDate, - aqDateTime.GetDay(InputDate)+1) # Using US week day number return aqDateTime.GetDayOfWeek(StartDate) # Using ISO week day number # return ISODayOfWeek(StartDate) def EndOfMonthDay (InputDate): # If the input parameter is omitted then current date is taken if InputDate == undefined: InputDate = aqDateTime.Today() DayNo = aqDateTime.GetDay(InputDate) MonthNo = aqDateTime.GetMonth(InputDate) YearNo = aqDateTime.GetYear(InputDate) EndDate = aqDateTime.AddDays(InputDate, - DayNo + DaysInMonth(MonthNo, YearNo)) # Using US week day number return aqDateTime.GetDayOfWeek(EndDate) # Using ISO week day number # return ISODayOfWeek(EndDate)