<jupyter_start><jupyter_text>Chapter 08 -- Date, Time, and Timedelta Objects  Topics Covered: String Literal Mapped to datetime timestamp  date objects  strftime() and strptime() methods  dateutil.parser  time objects  timedelta objects  Resources     Chapter 3, Data Types and Formatting briefly introduces Python date and datetimes.  This chapter covers Python Date, Time, and Datetime objects and details for handling these objects as well as mapping strings to datetime values and the reverse operation.  By understanding the lower-level behaviors of Date and Time objects, you will be able to grasp  Chapter 9, Pandas Time Series Capabilities and Datetime Handling.Many time series have fixed interval or frequency, for example, home sales on a monthly basis or web log record processed every 15 seconds.  Time series may also have irregular frequencies, in which case you may need to standardize, reshape, or change frequencies.  Definitions    - Timestamps are instances in time    - Periods such as the current month of current year        - Intervals indicated by start and end timestampsRecall, you can always return an object's type with the type method:    type()     In Python the datetime class be broken down into 5 categories:The first 4 will be examined briefly.       Object Type      Description     SAS Analogs       date      Stores calendar date(year, month, & day)      SAS date value = ' 24Oct16 ' d           time      Stores time (hours, minutes, seconds, & microseconds)      SAS time value = ' 12:34:56 ' t           datetime      Stores date & time together      SAS datetime value = ' 14Oct16:12:34:56 ' dt          timedelta      The difference between two datetime values      SAS datetime interval functions           tzinfo      Hanldes timezone related issues      Not generally dealt with<jupyter_code>from datetime import date, time, datetime, timedelta
import numpy as np
import pandas as pd
from pandas import Series, DataFrame, Index<jupyter_output><empty_output><jupyter_text>String Literal Mapped to datetime timestamp A timestamp is time value that represents a count of the number of seconds from the start of an epoch.  This is similiar to SAS datetime values that represent an off-set from an epoch beginning at midnight.<jupyter_code>pdt = pd.Timestamp('2016-10-24')
type(pdt)<jupyter_output><empty_output><jupyter_text>date objects The syntax for constructing a date object is:    date(year = yyyy, month = mm, day = dd)        Where: yyyy is an integer ranging from 1 to 9999 by default           mm is an integer ranging from 1 to 12 inclusive           dd is an integer ranging from 1 to the number of days in the month of the yearThe details for the date object are found  here        Construct an arbitrary date<jupyter_code>ind_day = date(1776, 7, 4)
print(ind_day)
print(type(ind_day))<jupyter_output>1776-07-04
<class 'datetime.date'><jupyter_text>Return today's date.  The SAS analog is the today() function.<jupyter_code>date.today()<jupyter_output><empty_output><jupyter_text>The .year, .month, and .day attribute for datetime objects returns year, month, and day respectively.  These attributes return integers.  SAS has the analog functions, year(), month(), day(), used to return the respective portions of a SAS datetime value. These functions return numeric values.<jupyter_code>print('Year:', date.today().year)
print('Month:', date.today().month) 
print('Day:', date.today().day)<jupyter_output>Year: 2016
Month: 11
Day: 13<jupyter_text>The analog SAS program for the examples in cells 3 to 6 is below. ````    /******************************************************/    /* c08_datetime_functions1.sas                        */    /******************************************************/    37       data _null_;    38           39       today = today();    40       ind_day = '04Jul1776'd;    41           42       today_f = put(today,mmddyy10.);    43       put 'unformatted, today is: ' today /    44           'formatted with mmddyy10. , today is: ' today_f;    45           46       m = month(today);    47       d = day(today);    48       y = year(today);    49           50       put 'Month returns: ' m    51           ' Day returns: ' d    52           ' Year returns ' y;    unformatted, today is: 20748    formatted with mmddyy10. , today is: 10/21/2016    Month returns: 10  Day returns: 21  Year returns 2016````   The .year, .month, and .day attributes also work with arbitrary dates as well.<jupyter_code>print('Year:', ind_day.year, 'Month:', ind_day.month, 'and day:', ind_day.day)<jupyter_output>Year: 1776 Month: 7 and day: 4<jupyter_text>The weekday() method returns an integer representing day of the week where Monday is 0 and Sunday is 6.  The SAS analog is the WEEKDAY() function that returns numeric where 1 is Sunday and Saturday is 7.<jupyter_code>print(date.weekday(ind_day))<jupyter_output>3<jupyter_text>strftime() and strptime() methods Like SAS, when working with datetime objects, formatting is needed to render dates into familiar date and time designations.  In cell  9 below, we render the constituent parts of the ind_day object created in cell 2 above.  We also need formatting when creating datetime objects from string representations of datetime illustrated below.The strftime() method (string formatter for time) is used to create string repersentations of Python datetime objects. The strptime() method (string parser for time) is used to create datetime objects from string representations of datetime.The directives for formatting both are found  here. SAS formats are analogs to the strftime() method.  SAS informats are analogs to the strptime() method.    strftime examples<jupyter_code>print('Day:', ind_day.strftime('%A'))
print('The convential method to display the date is:', ind_day.strftime('%c'))
print('Another way to display the date is:', ind_day.strftime('%A %B %d, %Y'))<jupyter_output>Day: Thursday
The convential method to display the date is: Thu Jul  4 00:00:00 1776
Another way to display the date is: Thursday July 04, 1776<jupyter_text>The SAS example below illustrate these commonly used SAS formats:    date11. ddmmyy10.    weekdate17.     yymmdd10.    The strftime() method apply format directives to datetime objects.  As illustrated above, these directives can be combined to form the desired output.  This includes any arbitrary characters such as comma, slash, or white-space needed to form the output.<jupyter_code>last_day = date(2016, 12, 31)
print('Last day is:', last_day.strftime("%d-%b-%Y"))        # date11. format
print('Last day is:', last_day.strftime("%d/%m/%Y"))        # ddmmyy10. format
print('Last day is:', last_day.strftime("%a, %b %d, %Y"))   # weekdate17. format
print('Last day is:', last_day.strftime("%Y-%m-%d"))        # yymmdd10. format<jupyter_output>Last day is: 31-Dec-2016
Last day is: 31/12/2016
Last day is: Sat, Dec 31, 2016
Last day is: 2016-12-31<jupyter_text>The SAS program below illustrates formats to map datetime values into string representation similiar to the strftime() method. ````    /******************************************************/    /* c08_lastday_formats.sas                            */    /******************************************************/    4         data _null_;    5         last_day = '31Dec16'd;    6             7         ld_f1 = put(last_day, date11.);    8         ld_f2 = put(last_day, ddmmyy10.);    9         ld_f3 = put(last_day, weekdate17.);    10        ld_f4 = put(last_day, yymmdd10.);    11            12        put 'Last day is: ' ld_f1;    13        put 'Last day is: ' ld_f2;    14        put 'Last day is: ' ld_f3;    15        put 'Last day is: ' ld_f4;    Last day is: 31-DEC-2016    Last day is: 31/12/2016    Last day is: Sat, Dec 31, 2016    Last day is: 2016-12-31````    The strptime() method is used to create or parse a datetime object from a string representation of datetime corresponding to the format string supplied.  See the example below in cell 9.<jupyter_code>str_date = "01/01/2016"
first_date = datetime.strptime(str_date, "%d/%m/%Y" )
print(first_date)
print('type for str_date is:', type(str_date))
print('type for first_date is:', type(first_date))<jupyter_output>2016-01-01 00:00:00
type for str_date is: <class 'str'>
type for first_date is: <class 'datetime.datetime'><jupyter_text>The SAS program below illustrates informats to map string representations of datetime into a SAS datetime value similiar to the strptime() method. ````    /******************************************************/    /* c08_informat_string_to_datetime.sas                */    /******************************************************/    45        data _null_;    46            47        str_date = "01/01/2016";    48            49        first_date = input(str_date, ddmmyy10.);    50            51        put first_date ddmmyy10.;    01/01/2016````  dateutil.parser It can be tedious to constantly write the directives used to control the strptime() method.  A useful alternative is to use the third-party dateutil.parser.  It can parse nearly any datetime string literals into datetime objects.<jupyter_code>from dateutil.parser import parse<jupyter_output><empty_output><jupyter_text><jupyter_code>strt_yr = parse('2016/01/01')
strt_yr<jupyter_output><empty_output><jupyter_text>Basic date aritmetic illustrating the replace() method.<jupyter_code>d = date(2015, 12, 31)
if d == date(2015, 12, 31):
    d2 = d.replace(day=25) == date(2015, 12, 25)
print(d)
print(d2)<jupyter_output>2015-12-31
True<jupyter_text><jupyter_code>today = date.today()

birth_day = date(today.year, 1, 24)

if birth_day < today:
    birth_day = birth_day.replace(year=today.year + 1)
print('Next birthday is:', birth_day)

days_until = abs(birth_day - today)
print(days_until)
print(type(days_until))<jupyter_output>Next birthday is: 2017-01-24
72 days, 0:00:00
<class 'datetime.timedelta'><jupyter_text>The example above in cell 11 is another illustration of date arithmetic.  The if condition determine whether the birthday has occured this year (in this case, True) and if True, uses the date.replace() method to increment to the next year.  The syntax:    days_until = abs(birth_day - today)    returns a timedelta.  As the name suggests, it is a duration period.  Additional examples of working with timedelta objects is below. The analog SAS program for counting the number of days until the next birthday is below.  In both the Python and SAS examples had we added 365 days in the conditional branch of the program the results would have been 94 days since 2016 is a leap year.  This is a  reminder that short-cuts like adding 365.25 to increment to the next year or adding 24 hours to increment to the following day is fraught with unintended consequences.  That is why these functions and operators are available. ````    /******************************************************/    /* c08_birthdate_calculation.sas                      */    /******************************************************/    35       data _null_;    36           37       today = today();    38           39       birth_day = '24Jan16'd;    40           41       if birth_day < today then do;    42          next_birth_day = intnx('year', birth_day, 1, 'sameday');    43          f_b_day = put(next_birth_day, mmddyy10.);    44          put 'Next birthday is: ' f_b_day;    45       end;    46           47       days_until = abs(next_birth_day - today);    48       put days_until ' days';    Next birthday is: 01/24/2017    95  days````  time objects The time object behaves similiar to the date object with respect to displaying and mapping string representations of time into time objects.  The SAS analogs are similar as well.  The syntax for constructing a time object is:    time(hour=hh, minute=mm, second=0ss, microsecond=ms)        Where hh is 0 <= hour < 24          mm is 0 <= minute < 60          ss is 0 <= second < 60          ms is 0 <= microsecond < 1000000          The time object has two other parameters, tzinfo and fold outside the scope of these examples.  The details for the time object are found  here .<jupyter_code>go_time = time(12, 34, 56)
print(go_time)
type(go_time)<jupyter_output>12:34:56<jupyter_text>Get the current time of day.  The SAS analog is the time() function.<jupyter_code>datetime.now()<jupyter_output><empty_output><jupyter_text><jupyter_code>print(datetime.now().hour)
print(datetime.now().minute) 
print(datetime.now().second)<jupyter_output>16
9
29<jupyter_text>The .hour, .minute, and .second attribute for datetime objects returns hour, minutes, and seconds respectively.  These attributes return integers.  SAS has the analog functions, hour(), minute(), second(), used to return the respective portions of a SAS datetime value. These functions return numeric values. ````    /******************************************************/    /* c08_datetime_functions2.sas                        */    /******************************************************/    21       data _null_;    22           23       now = time();    24           25       go_time = "12:34:45"t;    26           27       now_f = put(now, time8.);    28       put 'unformatted, now is ' now /    29           'formatted with time8., now is: ' now_f;    30           31       h = hour(now);    32       m  = minute(now);    33       s = second(now);    34           35       put 'hour returns: ' h    36           ' minute returns: ' m    37           ' second returns: ' s;    unformatted, now is 57327.064    formatted with time8., now is: 15:55:27    hour returns: 15  minute returns: 55  second returns: 27.063999891````   The .hour, .minute, and .second attribute also work with arbitrary times.<jupyter_code>print('Hour:', go_time.hour, 'Minutes:', go_time.minute, 'and seconds:', go_time.second)<jupyter_output>Hour: 12 Minutes: 34 and seconds: 56<jupyter_text>timedelta objects As the name suggests, a timedelta object represents the difference two date or times.  In other words, a duration.The details for the timedelta object are found  here   The SAS analog are the various date interval functions such as:INTNX INTGET  INTFIT and others that are similiar.    The results of an operation with a timedelta object returns a datetime object.  The datetime method now() returns today's date similiar to the SAS function TODAY().<jupyter_code>today = date.today()
moment = datetime.now().time()
now = datetime.combine(today, moment)<jupyter_output><empty_output><jupyter_text><jupyter_code>print(today, moment, now)<jupyter_output>2016-11-13 16:09:29.487036 2016-11-13 16:09:29.487036<jupyter_text>What is 1000 days from now<jupyter_code>today+timedelta(days=1000)<jupyter_output><empty_output><jupyter_text><jupyter_code>future = date(2020, 1, 1)
days_until = future - today
days_until<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11727064529166105, 'fraction_numerical': 0.04337868786205038, 'mean_word_length': 3.566902491541064, 'pattern_counts': {'":': 0, '<': 90, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '22', 'dir': 'jupyter-structured-clean-dedup', 'id': '301539', 'license': 'MIT', 'n_tokens_mistral': 4708, 'n_tokens_neox': 4115, 'n_words': 1668, 'path': 'Chapter07 - Date, Time, and  Timedelta Objects.ipynb', 'repo_name': 'ivenkwan/skillmodernization', 'size': '14846'}