Inverse of .tm_yday - python-3.x

I'm trying to do the inverse of calculating the yearday of a date (see code below), e.g. I would like to create a date from a integer number which is my 'yearday'.
Finding tm_day of a date:
from datetime import date
d = date(2015,12,1)
yearday = d.timetuple().tm_yday
Finding date of an integer (e.g. 335) and a given year (e.g. 2015):
???

I managed to solve this question with help of Is there an inverse of python's date.timetuple().tm_yday?
from datetime import datetime, timedelta
date_first_jan = date(2015, 1, 1)
date_new = date_first_jan + timedelta(335)

Related

transform timestamp (Seconds sins 1.1.1904) from NetCDF file

even there are several posts concerning NetCDF files and timestamp conversion I draw a blank today.
I
read in a NetCDF data set (version 3), and after I call variables information:
# Load required Python packages
import netCDF4 as nc
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
import pandas as pd
#read in a NetCDF data set
ds = nc.Dataset(fn)
# call time variable information
print(ds['time'])
As answer I get:
<class 'netCDF4._netCDF4.Variable'>
float64 time(time)
units: seconds since 1904-01-01 00:00:00.000 00:00
long_name: time UTC
axis: T
unlimited dimensions: time
current shape = (5760,)
filling on, default _FillValue of 9.969209968386869e+36 used
Now I would like to transform the seconds since 1.1.1904 time stamp into a DD.MM.YYYY HH:MM:SS.sss format. (by the way: why is there a second 00:00 information included after the time stamp?)
(1) I tried:
t = ds['time'][:]
dtime = []
dtime = (pd.to_datetime(t, format='%d.%m.%Y %H:%M:%S.micros') - datetime(1904, 1, 1)).total_seconds()
And I get the error:
pandas_libs\tslibs\strptime.pyx in pandas._libs.tslibs.strptime.array_strptime()
time data '3730320000' does not match format '%d.%m.%Y %H:%M:%S' (match)
(2) I tried:
d = datetime.strptime("01-01-1904", "%m-%d-%Y")
dt = d + timedelta(seconds=(t))
I get the
TypeError: unsupported type for timedelta seconds component: MaskedArray
(3) I tried
d = datetime.strptime("%m-%d-%Y", "01-01-1904")
dt = d + timedelta(seconds=(ds['time']))
And I get the answer:
unsupported type for timedelta seconds component: netCDF4._netCDF4.Variable
Has somebody a clearer view on the solution than I have at the moment?
Thanks,
Swawa
The NetCDF4 python library has a method for this: num2date().
https://unidata.github.io/netcdf4-python/#num2date. No need for datetime module.
NetCDF4 variables contain metadata attributes which describe the variable as seen in the output to your print:
print(ds['time']) #In particular the time variable units attribute.
# t contains just the numeric values of the time in `seconds since 1904-01-01 00:00:00.000 00:00`
t = ds['time'][:]
dtime = []
# t_var is the NetCDF4 variable which has the `units` attribute.
t_var = ds.['time']
#dtime = (pd.to_datetime(t, format='%d.%m.%Y %H:%M:%S.micros') - datetime(1904, 1, 1)).total_seconds()
dtime = NetCDF4.num2date(t, t_var.units)
The above should give you all the times in the dtime list as datetime objects.
print(dtime[0].isoformat())
print(dtime[-1].isoformat())
A simpler way would be:
dtime = NetCDF4.num2date(ds['time'][:], ds['time].units)

How to get 1st calendar day of the current and next month based on a current date variable

I have a date variable calls today_date as below. I need to get the 1st calendar day of the current and next month.
In my case, today_date is 4/17/2021, I need to create two more variables calls first_day_current which should be 4/1/2021, and first_day_next which should be 5/1/2021.
Any suggestions are greatly appreciated
import datetime as dt
today_date
'2021-04-17'
Getting just the first date of a month is quite simple - since it equals 1 all the time. You can even do this without needing the datetime module to simplify calculations for you, if today_date is always a string "Year-Month-Day" (or any consistent format - parse it accordingly)
today_date = '2021-04-17'
y, m, d = today_date.split('-')
first_day_current = f"{y}-{m}-01"
y, m = int(y), int(m)
first_day_next = f"{y+(m==12)}-{m%12+1}-01"
If you want to use datetime.date(), then you'll anyway have to convert the string to (year, month, date) ints to give as arguments (or do today_date = datetime.date.today().
Then .replace(day=1) to get first_day_current.
datetime.timedelta can't add months (only upto weeks), so you'll need to use other libraries for this. But it's more imports and calculations to do the same thing in effect.
I found out pd.offsets could accomplish this task as below -
import datetime as dt
import pandas as pd
today_date #'2021-04-17' this is a variable that is being created in the program
first_day_current = today_date.replace(day=1) # this will be 2021-04-01
next_month = first_day_current + pd.offsets.MonthBegin(n=1)
first_day_next = next_month.strftime('%Y-%m-%d') # this will be 2021-05-01

String time convert to only timestamp using python

I have a time 00:11:21.600000 like this in each row of excel I want to convert to time stamp in hrs and mins
Adding onto Juilian Focks answer, if you have a column named df["time"], you can convert each element into timestamp object by iterating over it as :
from datetime import datetime
for i in range(0,len(df["time"])):
df["time"][i] = df["time"][i].strftime("%H:%M")
or you could use list comprehension as :
dt_array = [x.strftime("%H:%M") for x in df["time"]]
then dt_array contains whole column as datetime object
You can use the inbuilt datetime module:
from datetime import datetime
your_time = datetime.strptime('00:11:21.600000', '%H:%M:%S.%f')
Then you have a datetime object your_time on which you can perform different actions, for example:
Get str with hours and minutes: your_time.strftime('%H:%M')
For more methods see the docs here.

Rounding datetime to the nearest hour

I have a question very similar to this one and this one but I'm stuck on some rounding issue.
I have a time series from a netCDF file and I'm trying to convert them to a datetime format. The format of the time series is in 'days since 1990-01-01 00:00:00'. Eventually I want output in the format .strftime('%Y%m%d.%H%M'). So for example I read my netCDF file as follows
import netCDF4
nc = netCDF4.Dataset(file_name)
time = np.array(nc['time'][:])
I then have
In [180]: time[0]
Out[180]: 365
In [181]: time[1]
Out[181]: 365.04166666651145
I then did
In [182]: start = datetime.datetime(1990,1,1)
In [183]: delta = datetime.timedelta(time[1])
In [184]: new_time = start + delta
In [185]: print(new_time.strftime('%Y%m%d.%H%M'))
19910101.0059
Is there a a way to "round" to the nearest hour so I get 19910101.0100?
You can round down with datetime.replace(), and round up by adding an hour to the rounded down value using datetime.timedelta(hours=1).
import datetime
def round_to_hour(dt):
dt_start_of_hour = dt.replace(minute=0, second=0, microsecond=0)
dt_half_hour = dt.replace(minute=30, second=0, microsecond=0)
if dt >= dt_half_hour:
# round up
dt = dt_start_of_hour + datetime.timedelta(hours=1)
else:
# round down
dt = dt_start_of_hour
return dt
Note that since we're using replace the values we're not replacing (like the timezone - tzinfo) will be preserved.
I don't think datetime provides a way to round times, you'll have to provide the code to do that yourself. Something like this should work:
def round_to_hour(dt):
round_delta = 60 * 30
round_timestamp = datetime.datetime.fromtimestamp(dt.timestamp() + round_delta)
round_dt = datetime.datetime.fromtimestamp(round_timestamp)
return round_dt.replace(microsecond=0, second=0, minute=0)

datetime converting format in python

have list of an other lists that contains date (y,m,d h,m,s,ms), and an other list of some values. I would plot this values in function of date but I couldn't convert the first list on date. How can I do this?
import datetime
import matplotlib
from time import mktime
import datetime as dt
from datetime import datetime
date = [
['"2017/10/27"', '"08:18:12"', ' 0.400'],
['"2017/10/27"', '"08:18:12"', ' 0.500'],
['"2017/10/27"', '"08:18:12"', ' 0.600']
]
values = [2,4,5]
for i in range(len(date)):
date[i][0] = eval(date[i][0])
date[i][1] = eval(date[i][1])
date[i][2] = date[i][2].strip()
date = [' '.join(elem) for elem in date]
>>>['2017/10/27 08:18:12 0.400', '2017/10/27 08:18:12 0.500', '2017/10/27
08:18:12 0.600']
date = [mktime(datetime.strptime(elem,'%Y-%m-%d %H:%M:%S
0.%f').timetuple()) for elem in date]
>>ValueError: time data '2017/10/27 08:18:12 0.400' does not match format
'%Y-%m-%d %H:%M:%S 0.%f
I have lists of thousands of lines so if some could this more efficiently I'll be very grateful. thank you in advance.
Your error message actually tells you exactly what's wrong :) The python function you're using, does pattern matching to find the different elements (minutes, hours, etc) in your time string.
You're using:
date = [mktime(datetime.strptime(elem,'%Y-%m-%d %H:%M:%S 0.%f').timetuple()) for elem in date]
but your time string is '2017/10/27 08:18:12 0.400'. You're using / and not - as a separator, so the function above can't find a matching string. Change your code above to:
date = [mktime(datetime.strptime(elem,'%Y/%m/%d %H:%M:%S 0.%f').timetuple()) for elem in date]

Resources