assert isinstance(safe_date('2024-12-15 21:02:17'), datetime)
assert isinstance(safe_date('2024/12/15 21:02:17'), datetime)
assert isinstance(safe_date('2024.12.15 21:02:17'), datetime)
assert isinstance(safe_date('2024-12-15'), datetime)
assert isinstance(safe_date('2024/12/15'), datetime)
assert isinstance(safe_date('2024.12.15'), datetime)
assert isinstance(safe_date(datetime.now()), datetime)core
Legacy function from former package finutilities
Set of functions that are transferred from my former package finutilities
safe_date
def safe_date(
dt:str | datetime.datetime, # date time to validate or convert
)->datetime: # datetime type object
Return a datetime object from string or datetime
Accepted formats:
- ‘YYYY-MM-DD’, ‘YYYY/MM/DD’, ‘YYYY.MM.DD’
- ‘HH:MM:SS’ can be added to the above formats
This function converts date-time strings into a datetime object, as long as the strings are in one of the following formats:
2024-12-15 21:02:172024/12/15 21:02:172024.12.15 21:02:172024-12-152024/12/152024.12.15
The function also accepts a datetime as argument dt and can be used to ensure a data argument used in a function is a datetime object.
time_slice_df
def time_slice_df(
df:DataFrame, # `df` that will be sliced, must have a `DateTimeIndex`
start:str | datetime.datetime | None=None, # start date for slicing
end:str | datetime.datetime | None=None, # end date for slicing
)->DataFrame: # sliced `df`
Slices DataFrame’s rows from start to end, or the closest datetime available in the DataTimeIndex.
Even if we pass start and end dates that are not in the datafrane DateTimeIndex, the function still will slice using the closest datetime(s) in the index.
Let’s take an test dataframe for illustration.
load_test_df
def load_test_df(
)->DataFrame:
df = load_test_df()
df.iloc[:15, :]| Open | High | Low | Close | Volume | |
|---|---|---|---|---|---|
| dt | |||||
| 2018-10-22 | 2759.02 | 2779.27 | 2747.27 | 2754.48 | 26562 |
| 2018-10-23 | 2753.11 | 2755.36 | 2690.69 | 2743.45 | 38777 |
| 2018-10-24 | 2744.83 | 2748.58 | 2651.23 | 2672.80 | 41777 |
| 2018-10-25 | 2670.80 | 2722.90 | 2657.93 | 2680.71 | 39034 |
| 2018-10-26 | 2675.59 | 2692.34 | 2627.59 | 2663.57 | 61436 |
| 2018-10-29 | 2667.70 | 2707.00 | 2603.33 | 2639.17 | 44960 |
| 2018-10-30 | 2639.55 | 2689.50 | 2633.05 | 2688.50 | 52786 |
| 2018-10-31 | 2688.88 | 2736.76 | 2681.25 | 2704.75 | 32374 |
| 2018-11-01 | 2707.13 | 2741.58 | 2706.88 | 2731.90 | 29565 |
| 2018-11-02 | 2725.28 | 2766.28 | 2699.96 | 2723.76 | 41892 |
| 2018-11-05 | 2721.51 | 2744.41 | 2713.14 | 2740.26 | 25161 |
| 2018-11-06 | 2739.39 | 2761.53 | 2730.14 | 2759.15 | 20481 |
| 2018-11-07 | 2757.28 | 2816.63 | 2745.53 | 2815.88 | 29723 |
| 2018-11-08 | 2814.76 | 2817.01 | 2794.68 | 2805.02 | 18369 |
| 2018-11-09 | 2803.40 | 2810.15 | 2763.78 | 2778.60 | 25123 |
In this example, the DataFrame misses a few days, e.g.: - 2018-10-27 and 2018-10-28 - 2018-11-03 and 2018-11-04
If we pick one of these dates for start and end respectively, we still get a sampled dataframe with the closed existing dates:
time_slice_df(df, '2018-10-27', '2018-11-04')| Open | High | Low | Close | Volume | |
|---|---|---|---|---|---|
| dt | |||||
| 2018-10-29 | 2667.70 | 2707.00 | 2603.33 | 2639.17 | 44960 |
| 2018-10-30 | 2639.55 | 2689.50 | 2633.05 | 2688.50 | 52786 |
| 2018-10-31 | 2688.88 | 2736.76 | 2681.25 | 2704.75 | 32374 |
| 2018-11-01 | 2707.13 | 2741.58 | 2706.88 | 2731.90 | 29565 |
| 2018-11-02 | 2725.28 | 2766.28 | 2699.96 | 2723.76 | 41892 |