How to print only if specific time starts with x in Python - python

Hi I'm a newbie learning python and I want to print something only if current time starts with x (for example, if current time starts with = 4, print "hi", time = 4:18), this is the code I made, it says attribute error:
import datetime
local = datetime.datetime.now().time().replace(microsecond=0)
if local.startswith('16'):
print("Hi! It's ", local)

The .replace() method returns a date object. date objects don't have a .startswith() method. That method is only for str.
Try converting your date to a string first:
if str(local).startswith('16'):
print("Hi! It's ", local)
The documentation lists all of the methods available on a date object.

You need to first convert it to a string, as datetime objects have no startswith() method. Use strftime, example:
import datetime
t = datetime.datetime(2012, 2, 23, 0, 0)
t2 = t.strftime('%m/%d/%Y')
will yield:
'02/23/2012'. Once it's converted, you can use t2.startswith().
https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior

You can get the hour of the time and check if it is 16:
if local.hour == 16:
print("Hi! It's ",local)
If you need to use startswith() then you can convert it to a string like this:
if str(local).startswith('16'):
print("Hi! It's ", local)

That's not a good way. Check the time as int is the better solution here.
replace() has 2 needed str arguments. You use a named attribute which doesn't exist.

Related

Use variables as keywords for functions with pre-defined keywords (Python)

I'm trying to create a simple function that allows a user to input basic information that will change the values of a datetime object, and I'd like to find a way to make it as clean as possible by using a variable as a keyword. This can easily be done a different way, but I figured it'd be useful to know how to replace pre-set keywords.
The datetime object has a .replace() method that takes any time value as a keyword:
datetime.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])
But I want to allow the user to specify how much of which kind of time (e.g., 2 days; 4 hours; 1 month).
I'm trying to replace any of the above keywords up to "minute" with whatever the user inputs, which is stored in the time_type variable, but I get "TypeError: 'time_type' is an invalid keyword argument for this function".
start_time = datetime.datetime(2016, 09, 16, 15, 30)
def change_time(integer, time_string):
time_type = time_string.replace("s","") # de-pluralizes input
new_time = getattr(start_time, time_type) + integer
print(start_time.replace(time_type=new_time))
change_time(2, "days")
This should print the new start_time, which is (2016, 09, 18, 15, 30), but I just get an error.
Python allows you to store data in a dictionary and finally unpack them as keyword arguments to different functions.
For the thing that you want to do, best way to accomplish this is to use kwargs.
replacement_info = {'day': 2, 'month': 9, ...}
new_time = start_time.replace(**replacement_info)
Note the difference with what you've done. Passing time_type directly to replace, would result in replace being called with the time_type parameter, set to 2, which is undefined (since it's not in the list of accepted arguments for replace)
Instead you have to pass it like **{time_type: 2} to the replace function, this way, replace will receive the interpreted value for time_type, namely day, as the input.
So you need to change
print(start_time.replace(time_type=new_time))
to
print(start_time.replace(**{time_type:new_time})
You cannot replace keyword arguments on a function you did not write. When calling a function like:
f(a=b)
The value of a is not sent as an argument to f. Instead, the value of b is sent and that value is set to the argument a in f's argument list definition. If f does not have an argument a defined (as datetime.replace does not have a time_type argument defined), you will get an invalid keyword argument exception.
As others have said, to pass dynamic keyword arguments to a function use the **kwargs notation.
Change your last line to something like this:
year = start_time.year
month = start_time.month
day = start_time.day
hour = start_time.hour
minute = start_time.minute
second = start_time.second
microsecond = start_time.microsecond
exec(time_type + '='+str(new_time))
print(start_time.replace(year, month, day, hour, minute, second, microsecond)

How do I create a time object from a formatted string, in Python?

I am aware of the class method datetime.strptime, but that produces a datetime object, not a time object. I was expecting there to be something analogous for time objects, that would accept a format string such as "%H:%Mpm" to convert strings like this:
txt = "21:22pm"
to an object like this:
datetime.time(21, 22)
Is this the best I can do?:
datetime.strptime("21:22pm", "%H:%Mpm").time()

Datetime string format alignment

In Python 2.7 I want to print datetime objects using string formatted template. For some reason using left/right justify doesn't print the string correctly.
import datetime
dt = datetime.datetime(2013, 6, 26, 9, 0)
l = [dt, dt]
template = "{0:>25} {1:>25}" # right justify
print template.format(*l) #print items in the list using template
This will result:
>25 >25
Instead of
2013-06-26 09:00:00 2013-06-26 09:00:00
Is there some trick to making datetime objects print using string format templates?
It seems to work when I force the datetime object into str()
print template.format(str(l[0]), str(l[1]))
but I'd rather not have to do that since I'm trying to print a list of values, some of which are not strings. The whole point of making a string template is to print the items in the list.
Am I missing something about string formatting or does this seem like a python bug to anyone?
SOLUTION
#mgilson pointed out the solution which I missed in the documentation. link
Two conversion flags are currently supported: '!s' which calls str()
on the value, and '!r' which calls repr().
Some examples:
"Harold's a clever {0!s}" # Calls str() on the argument first
"Bring out the holy {name!r}" # Calls repr() on the argument first
The problem here is that datetime objects have a __format__ method which is basically just an alias for datetime.strftime. When you do the formatting, the format function gets passed the string '>25' which, as you've seen, dt.strftime('>25') just returns '>25'.
The workaround here it to specify that the field should be formatted as a string explicitly using !s:
import datetime
dt = datetime.datetime(2013, 6, 26, 9, 0)
l = [dt, dt]
template = "{0!s:>25} {1!s:>25} "
out = template.format(*l)
print out
(tested on both python2.6 and 2.7).
datetime.datetime has format method. You need to convert it str.
>>> '{:%Y/%m/%d}'.format(dt)
'2013/06/26'
>>> '{:>20}'.format(dt)
'>20'
>>> '{:>20}'.format(str(dt))
' 2013-06-26 09:00:00'
>>> import datetime
>>> dt = datetime.datetime(2013, 6, 26, 9, 0)
>>> l = [dt, dt]
>>> template = "{0:>25} {1:>25}"
>>> print template.format(*l)
>25 >25
>>> print template.format(*map(str, l))
2013-06-26 09:00:00 2013-06-26 09:00:00
Try this:
print template.format(*map(str, l))
=> 2013-06-26 09:00:00 2013-06-26 09:00:00
It works by first converting the datetime objects to a string, which then can be formatted with the format method without problems.

Retrieve UNIX TIMESTAMP in django api call

I have the following query:
users = Analytics.objects.values('date', 'users').order_by('date')
[(datetime.date(2012, 8, 20), 156L), (datetime.date(2012, 8, 21), 153L),...]
How would I get the unix timestamp of the datetime here? The equivalent of doing:
select concat(UNIX_TIMESTAMP(date), '000') as date, users from analytics_analytics
1345446000000 156
1345532400000 153
1345618800000 153
Note that I do not want to do formatting in python as there are a lot of the above calls that need to be done.
The best way to do this, if really want the DB to do the conversion (and this can be applicable for other things, in general when you want to return information that's not readily available in a column from the DB), you can use the QuerySet.extra() function https://docs.djangoproject.com/en/dev/ref/models/querysets/#extra like this:
Analytics.objects.extra(select={'timestamp': "CONCAT(UNIX_TIMESTAMP(date), '000')"}).order_by('date').values('timestamp', 'users')
Downside of this is that it's no longer DB agnostic, so when you change RDBMS, you have to change the code. Upside is you can use values with it, unlike a property on the model.
Python datetime.date objects don't have a time component, so the timestamp you want needs a little qualification. If midnight suffices, you can use the .timetuple() method together with the time.mktime() function to create a timestamp:
>>> import datetime, time
>>> adate = datetime.date(2012, 8, 20)
>>> print time.mktime(adate.timetuple())
1345413600.0
If you need a specific time in the day, use the datetime.datetime.combine() class method to construct a datetime, then use the same trick to make it a timestamp:
>>> adatetime = datetime.datetime.combine(adate, datetime.time(12, 0))
>>> print time.mktime(adatetime.timetuple())
1345456800.0
Use either as a property on your Django model:
class Analytics(models.Model):
#property
def timestamp(self):
return time.mktime(self.date.timetuple())
I am not familiar with UNIX_TIMESTAMP, but with regard to Django: why not create a calculated field as proprty at your Django Model
class Analytics(...):
...
#property
def unix_timestamp(self):
return time.mktime(self.date.timetuple())

Convert a datetime.date object into a datetime.datetime object with zeros for any missing time attributes

Is there a built-in function that converts a datetime.date object into a datetime.datetime object with 0's for the missing stuff? For example, suppose
tdate = datetime.date(2012,1,31)
I want to write something like either of these
tdatetime = datetime.date.datetime()
tdatetime = datetime.datetime(tdate)
and I want the output to be
datetime.datetime(2012, 1, 31, 0, 0)
But neither works. There is a builtin function to go from datetime.datetime to datetime.date, but I'm looking for the reverse operation.
One very poor solution would be to write:
datetime.datetime(tdate.year(), tdate.month(), tdate.day(), 0, 0)
I specifically want to avoid this bad way of doing it.
I've already written my own small function to do this, but I think it should be provided in the module. It's cluttering up some system-wide imports to use my function. It's workable, just not very Pythonic.
I'm just asking to see if anyone knows whether there is an efficient way to do it using only datetime module functions.
Use .combine(date, time) with an empty time instance:
>>> import datetime
>>> tdate = datetime.date(2012,1,31)
>>> datetime.datetime.combine(tdate, datetime.time())
datetime.datetime(2012, 1, 31, 0, 0)
If you like to use a constant instead, use time.min:
>>> datetime.datetime.combine(tdate, datetime.time.min)
datetime.datetime(2012, 1, 31, 0, 0)

Categories

Resources