Retrieve UNIX TIMESTAMP in django api call - python

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())

Related

How to print only if specific time starts with x in 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.

How to use lazy_attribute with Faker in Factory Boy

Context:
I have a model with two dates, I want to use factory.Faker for both of them but the second date should always be greater that the first one.
I tried this:
Model excerpt:
class Event(models.Model):
execution_start_date = models.DateTimeField()
execution_end_date = models.DateTimeField()
Factory:
class EventFactory(factory.DjangoModelFactory):
class Meta:
model = Event
strategy = factory.BUILD_STRATEGY
execution_start_date = factory.Faker('date_time_this_year', tzinfo=pytz.utc)
#factory.lazy_attribute
def execution_end_date(self):
return factory.Faker('date_time_between_dates',
datetime_start=self.execution_start_date,
datetime_end=now(),
tzinfo=pytz.utc)
But when I try to use the factory from the python shell I got this:
In [3]: e = EventFactory()
In [4]: e.execution_end_date
Out[4]: <factory.faker.Faker at 0x1103f51d0>
The only way I managed to make it work was with like this:
#factory.lazy_attribute
def execution_end_date(self):
# return factory.Faker('date_time_between_dates',
# datetime_start=self.execution_start_date,
# datetime_end=now(),
# tzinfo=pytz.utc)
faker = factory.Faker._get_faker()
return faker.date_time_between_dates(datetime_start=self.execution_start_date,
datetime_end=now(),
tzinfo=pytz.utc)
But I honestly think there is a better way to do it.
My dependencies are:
Django (1.8.18)
factory-boy (2.8.1)
Faker (0.7.17)
When lazy_attribute come into play you already have generated object on your hand. So you can work with, for example, random and timedelta, like this:
#factory.lazy_attribute
def execution_end_date(self):
max_days = (now() - self.execution_start_date).days
return self.execution_start_date + timedelta(random.randint(1, max_days))
or some other way to generate random date. There is no point to stick to factory_boy.Faker
EDIT
After my first answer I manage to found a way to do what you want, it's really simple.You just need to call generate() method with empty dict from Faker:
#factory.lazy_attribute
def execution_end_date(self):
return factory.Faker('date_time_between_dates',
datetime_start=self.execution_start_date,
datetime_end=now(),
tzinfo=pytz.utc).generate({})
At first I was trying to do the same thing, but according to Factory Boy's documentation for the Faker wrapper, the parameters can be any valid declaration. That means that you're allowed to specify each of the faker's parameter as a SelfAttribute, LazyAttribute, etc. I don't know when this feature was first introduced, but version 3.1.0 (Oct 2020) docs mentions it for the first time.
I believe that the question's example can be rewritten as:
class EventFactory(factory.DjangoModelFactory):
class Meta:
model = Event
strategy = factory.BUILD_STRATEGY
execution_start_date = factory.Faker('date_time_this_year', tzinfo=pytz.utc)
execution_end_date = factory.Faker('date_time_between_dates',
datetime_start=factory.SelfAttribute('..execution_start_date'),
datetime_end='now',
tzinfo=pytz.utc)
So basically it's turned around and the faker's parameters are evaluated instead of the LazyAttribute's return value. In my example datetime_start now refers to whatever execution_start_date resolves to and datetime_end takes a literal string 'now', that the Faker library will replace with the current datetime.

How to ignore timezone when using bson.json_util.loads in python?

I'm dumping and loading bson to text files and my datetimes are having time zone info added to them. I do not want the time zone info added.
import bson, datetime
d1 = datetime.datetime.now()
d2 = bson.json_util.loads(bson.json_util.dumps(d1))
Results in d1:
datetime.datetime(2016, 8, 16, 14, 38, 41, 984544)
and d2 :
datetime.datetime(2016, 8, 16, 14, 56, 10, 155000, tzinfo=<bson.tz_util.FixedOffset object at 0x1042ca050>)
In this particular case I can do
d3 = d2.replace(tzinfo=None)
to remove the timezone. However, I'm doing this for a larger object with times all over the place among other types. Is there a way to instruct bson.json_util.loads to always set tzinfo=None when it tries to parse a datetime?
Interesting. The bson source directly overwrites object_hook so you can't pass in a custom one.
From the source here:
def loads(s, *args, **kwargs):
"""Helper function that wraps :class:`json.loads`.
Automatically passes the object_hook for BSON type conversion.
"""
kwargs['object_hook'] = lambda dct: object_hook(dct)
return json.loads(s, *args, **kwargs)
Their source (inside object_hook) is also explicitly setting the timezone, which is causing the behavior that you're seeing:
aware = datetime.datetime.strptime(
dt, "%Y-%m-%dT%H:%M:%S.%f").replace(tzinfo=utc)
if not offset or offset == 'Z':
# UTC
return aware
I think you're going to have to do another pass over your resulting data set to remove the time zones, if you absolutely can't have a time zone set.
EDIT: It looks like there is a pending change to add a JsonOptions class that would allow you to pass tz_aware=False. So if you can wait until the python driver updates to 3.4, you should be able to get your desired behavior.
Found myself here in 2021. This is how I resolved it:
import bson, datetime
d1 = datetime.datetime.now()
json_options = json_util.DEFAULT_JSON_OPTIONS.with_options(tz_aware=False, tzinfo=None)
d2 = bson.json_util.loads(bson.json_util.dumps(d1), json_options=json_options)

Comparing time in a datetime object python

I am having a weird problem.
I am running a django app and in one of my models I have a method to compare the time that the user gives and the time that is stored in the model db
So, for debugging purposes, I do this.
print self.start
print start
print self.start.time < start.time
And the output is:
2012-10-15 01:00:00+00:00
2012-10-22 01:01:00+00:00
False
HOW IS THIS POSSIBLE?!?!?!
I tried this in the django shell and in the python cli! Both give me True! With the same values.
Thanks guys.
.time is a method, not a property.
>>> import datetime
>>> a = datetime.datetime(2012, 10, 15, 1, 0, 0)
>>> a.time
<built-in method time of datetime.datetime object at 0x10049f508>
>>> a.time()
datetime.time(1, 0)
Therefore, the correct code would be if self.start.time() < start.time().

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