I'm playing around with getting a string with date format and values transformed to influxdb ready import.
Therefore I'm trying to transform the datetime to epoch timestamp in python.
What I've so far.
#Import of some modules
import re
from datetime import date
import time, os
#example text which I'll retrieve daily
txt = "daily power [{'date': datetime.datetime(2020, 12, 1, 0, 0), 'total_consumption_kwh': 0.483}, {'date': datetime.datetime(2020, 12, 2, 0, 0), 'total_consumption_kwh': 0.269}, {'date': datetime.datetime(2020, 11, 4, 0, 0), 'total_consumption_kwh': 0.611}, {'date': datetime.datetime(2020, 11, 5, 0, 0), 'total_consumption_kwh': 0.61}]"
#Regex patterns
date_regex = r'\d+,\s\d+,\s\d+'
consump_regex = r'\w+\':\s\d+.\d+'
regex_plug = r'\w+\(\d+\,\s\d+\,\s\d+\,\s\d+\,\s\d+\)\,\s\'\w+\'\:\s\d+\.\d+'
x= re.findall(regex_plug, txt)
nl = ("\n".join(x))
condition1 = str(nl).replace(",", "-")
condition2 = condition1.replace(" ", "",)
condition3 = condition2.replace("':", "': ")
condition4 = condition3.replace("(", "': ")
condition5 = condition4.replace(")-", " ")
condition6 = condition5.replace("d", "'d")
print(condition6)
results in:
'datetime': 2020-12-1-0-0 'total_consumption_kwh': 0.483
'datetime': 2020-12-2-0-0 'total_consumption_kwh': 0.269
'datetime': 2020-11-4-0-0 'total_consumption_kwh': 0.611
'datetime': 2020-11-5-0-0 'total_consumption_kwh': 0.61
The last step is to transform the time to epoch timestamp, but I don't get this working.
I found already some threads describing how to replace date to epoch. with
date_time = '2020-12-1-0-0' #should be txt
pattern = '%Y-%m-%d-%H-%M'
epoch = int(time.mktime(time.strptime(date_time, pattern)))
print(epoch)
But how can I process this over my condition6 string, to make the output:
'datetime': 1606780800 'total_consumption_kwh': 0.483
Using eval:
import datetime
txt = "daily power [{'date': datetime.datetime(2020, 12, 1, 0, 0), 'total_consumption_kwh': 0.483}, {'date': datetime.datetime(2020, 12, 2, 0, 0), 'total_consumption_kwh': 0.269}, {'date': datetime.datetime(2020, 11, 4, 0, 0), 'total_consumption_kwh': 0.611}, {'date': datetime.datetime(2020, 11, 5, 0, 0), 'total_consumption_kwh': 0.61}]"
daily_power = eval(txt.strip().strip("daily power"))
# Now just convert the datetimes to timestamps:
for d in daily_power:
d['date'] = d['date'].timestamp()
print(daily_power) # Yields wanted result.
An approach without using eval (due to safety etc):
from ast import literal_eval as leval
date_cons = re.findall(r'{[^\{\}]+}', txt)
for idx, dc in enumerate(date_cons):
dtnums = re.search(r'\((?:\d+,?\s*){5}\)', dc).group()
ts = datetime.datetime(*leval(dtnums)).timestamp()
date_cons[idx] = leval(re.sub('datetime\.datetime\(.+\)', str(ts), dc))
print(date_cons) # Yields wanted result.
If you dont even want to use literal_eval (which is safe) you can just use more regex.
Related
I am trying to come up with a way to create a list of dates n months back from given date dt. However, it seems to tricky based on what dt is. Below I am illustrating the dilemma through a few examples (esp. look at tricky case-3 below):
from datetime import datetime
from dateutil.relativedelta import relativedelta
# Simple case.
dt = datetime(2021, 2, 15)
dt - relativedelta(months=1) # n=1 gives datetime.datetime(2021, 1, 15, 0, 0)
dt - relativedelta(months=2) # n=2 gives datetime.datetime(2020, 12, 15, 0, 0)
# Simple case-2
dt = datetime(2021, 3, 31)
dt - relativedelta(months=1) # n=1 gives datetime.datetime(2021, 2, 28, 0, 0)
dt - relativedelta(months=2) # n=2 gives datetime.datetime(2021, 1, 31, 0, 0)
dt - relativedelta(months=3) # n=3 gives datetime.datetime(2020, 12, 31, 0, 0)
dt - relativedelta(months=4) # n=4 gives datetime.datetime(2020, 11, 30, 0, 0)
# Tricky case-3
dt = datetime(2021, 2, 28)
dt - relativedelta(months=1) # n=1 gives datetime.datetime(2021, 1, 28, 0, 0) and not datetime.datetime(2021, 1, 31, 0, 0)
dt - relativedelta(months=2) # n=2 gives datetime.datetime(2020, 12, 28, 0, 0) and not datetime.datetime(2020, 12, 31, 0, 0)
dt - relativedelta(months=3) # n=3 gives datetime.datetime(2020, 11, 28, 0, 0) and not datetime.datetime(2020, 11, 30, 0, 0)
dt - relativedelta(months=4) # n=4 gives datetime.datetime(2020, 10, 28, 0, 0) and not datetime.datetime(2020, 10, 31, 0, 0)
relativedelta seems to fail on the corner case of date is end of month while month has less than 31 days. Here's a work-around:
check if date is end of month
if not, simply use relativedelta
if so, use relativedelta but make sure the day is the last of the month by setting the day attribute explicitly
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
# add_month adds n months to datetime object dt
def add_month(dt, n):
# we can add a day without month changing - not end of month:
if (dt + timedelta(1)).month == dt.month:
return dt + relativedelta(months=n)
# implicit else: end of month
return (dt + relativedelta(months=n+1)).replace(day=1) - timedelta(1)
Examples:
d = datetime(2021, 3, 15)
print(add_month(d, -1).date(), d.date(), add_month(d, 1).date())
# 2021-02-15 2021-03-15 2021-04-15
d = datetime(2021, 3, 31)
print(add_month(d, -1).date(), d.date(), add_month(d, 1).date())
# 2021-02-28 2021-03-31 2021-04-30
d = datetime(2021,2,28)
print(add_month(d, -1).date(), d.date(), add_month(d, 1).date())
# 2021-01-31 2021-02-28 2021-03-31
d = datetime(2021,11,30)
print(add_month(d, -1).date(), d.date(), add_month(d, 1).date())
# 2021-10-31 2021-11-30 2021-12-31
I have a numpy array which contains hours from 4 days:
s = np.array([0.0, 1.0, 2.0, 3.0, 4.0 ....96.0])
I want to create a datetime object from that.
I know that the first element is at timestamp 2021-03-21 00:00,
so:
start_date = datetime.datetime.strptime('2021-03-21 00:00', '%Y-%m-%d %H:%M')
How can I create a new array which contains datetimes, incremented by an hour from the s array.
Use timedelta to build your new array:
>>> import numpy as np
>>> from datetime import datetime, timedelta
>>> s = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 96.0])
>>> start_date = datetime.strptime('2021-03-21 00:00', '%Y-%m-%d %H:%M')
>>> [start_date + timedelta(hours=diff) for diff in s]
[datetime.datetime(2021, 3, 21, 0, 0), datetime.datetime(2021, 3, 21, 1, 0), datetime.datetime(2021, 3, 21, 2, 0), datetime.datetime(2021, 3, 21, 3, 0), datetime.datetime(2021, 3, 21, 4, 0), datetime.datetime(2021, 3, 25, 0, 0)]
The below code:
import datetime as dt
fruit_lst = ['apple','orange','pear']
fruit_dict = {}
fruit_dict['datetime'] = dt.datetime(2020,1,1)
for fruit in fruit_lst:
fruit_dict[fruit] = 0
Produces this dictionary:
{'datetime': datetime.datetime(2020, 1, 1, 0, 0),
'apple': 0,
'orange': 0,
'pear': 0}
Is it possible (or desirable) to re-write that code into one line and generate the same output?
Thanks!
You can do:
fruit_dict = dict(datetime=dt.datetime(2020,1,1), **{f:0 for f in fruit_lst})
print(fruit_dict)
Prints:
{'datetime': datetime.datetime(2020, 1, 1, 0, 0), 'apple': 0, 'orange': 0, 'pear': 0}
but your explicit for-loop is more readable. I'd keep it that way.
I have finished my code and it works when I run it. However, I need to turn this into a function, that if I call the function and pass in any list of number, i can get the same results. This is my code:
from datetime import datetime, timedelta
dateStr = 'user-input'
dateObj = datetime.strptime(dateStr, '%Y%m%d')
timeStep = timedelta(days=1)
dateObj2 = dateObj + timeStep
days15 = [dateObj + timeStep*i for i in range(15)]
print(days15)
------------------ output:
datetime.datetime(2017, 1, 1, 0, 0),..
I need to be able to pass in
date_str = "20170817"
results = days_15(date_str)
print(results)
And then get the same results. Any hints? or any help - Thank you
You just need to add a def statement before your code to define the function, and rather than printing the result, return it:
from datetime import datetime, timedelta
def days_15(dateStr):
dateObj = datetime.strptime(dateStr, '%Y%m%d')
timeStep = timedelta(days=1)
return [dateObj + timeStep*i for i in range(15)]
my_date_str = "20170817"
results = days_15(my_date_str)
print(results)
Output:
[
datetime.datetime(2017, 8, 17, 0, 0), datetime.datetime(2017, 8, 18, 0, 0),
datetime.datetime(2017, 8, 19, 0, 0), datetime.datetime(2017, 8, 20, 0, 0),
datetime.datetime(2017, 8, 21, 0, 0), datetime.datetime(2017, 8, 22, 0, 0),
datetime.datetime(2017, 8, 23, 0, 0), datetime.datetime(2017, 8, 24, 0, 0),
datetime.datetime(2017, 8, 25, 0, 0), datetime.datetime(2017, 8, 26, 0, 0),
datetime.datetime(2017, 8, 27, 0, 0), datetime.datetime(2017, 8, 28, 0, 0),
datetime.datetime(2017, 8, 29, 0, 0), datetime.datetime(2017, 8, 30, 0, 0),
datetime.datetime(2017, 8, 31, 0, 0)
]
Hi I am saving year as string as "2011-2012" in db, i want to convert it to datetime object and save it in datetime object like "datetime.datetime(2011, 1, 1, 0, 0)-datetime.datetime(2012, 1, 1, 0, 0)"?
can you please help me
you could use rrule from the dateutil package:
from datetime import datetime
from dateutil.rrule import rrule, MONTHLY
# input string:
years = '2011-2012'
# map to integer:
years = tuple(map(int, years.split('-')))
# obtain a datetime object for the starting year and the total years:
start_year = datetime(years[0], 1, 1)
total_years = years[1]-years[0]
# use rrule to generate a monthly range:
monthrange = []
dt_range = list(rrule(freq=MONTHLY, count=total_years*12+1, dtstart=start_year))
# [datetime.datetime(2011, 1, 1, 0, 0),
# datetime.datetime(2011, 2, 1, 0, 0),
# datetime.datetime(2011, 3, 1, 0, 0),
# datetime.datetime(2011, 4, 1, 0, 0),
# datetime.datetime(2011, 5, 1, 0, 0),
# datetime.datetime(2011, 6, 1, 0, 0),
# datetime.datetime(2011, 7, 1, 0, 0),
# datetime.datetime(2011, 8, 1, 0, 0),
# datetime.datetime(2011, 9, 1, 0, 0),
# datetime.datetime(2011, 10, 1, 0, 0),
# datetime.datetime(2011, 11, 1, 0, 0),
# datetime.datetime(2011, 12, 1, 0, 0),
# datetime.datetime(2012, 1, 1, 0, 0)]