Something which I thought would be simple has become such a struggle.
I'm trying to format a datetime object.
From this 2016-06-17 09:56:53.289000+00:00 to 2016-06-17 09:56:53
This code I tried doesn't make any changes to the output. It skips right past it.
if type(field) is models.DateField:
if old_value != None:
old_value = old_value.strftime('%Y-%m-%d %H:%M:%S')[:-3]
if new_value != None:
new_value = new_value.strftime('%Y-%m-%d %H:%M:%S')[:-3]
Then I tried the following
if isinstance(new_value, datetime.datetime):
new_value = new_value.utcnow().strftime('%Y-%m-%d %H:%M:%S')[:-3]
if isinstance(old_value, datetime.datetime):
old_value = old_value.utcnow().strftime('%Y-%m-%d %H:%M:%S')[:-3]
However it removes any trace of the values of both new_value and old_value and displays nothing. Which is confusing me so much!
The end part of my code is as follows which displays the date:
if new_value != old_value:
print "%s does not match" % key
changes[key] = "Field %s %s updated to %s<br/>" % (key, old_value, new_value)
If anyone could point me in the right direction that would be great.
Try removing the .utcnow() call you added before your .strftime() calls. new_value.utcnow() invokes datetime.datetime.utcnow, which returns an entirely new datetime.datetime object representing the current time, which has nothing to do with new_value or old_value.
d = '2016-06-17 09:56:53.289000+00:00'
print(datetime.strptime(d[:19], '%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d %H:%M:%S'))
Just a simple snippet based on your code
In [11]: from datetime import datetime
In [12]: mytime = now.strftime("%Y-%m-%d %H:%M:%S")
In [13]: print(mytime)
2016-06-21 16:44:32
Related
When I call on datetime.now() in my program it calls the current time, but when I call it again, it displays the previous time. How can I update datetime.now() so it calls the current time eachtime?
You say:
but when I call it again
... but you're NOT calling it again. You're more-than-likely printing/outputting the value of the variable that the first datetime.now() was assigned to.
Let's say you have the following:
from datetime import datetime
first_time = str(datetime.now())
print('First datetime.now() value: %s' % first_time)
You're probably attempting to get the updated time by simply printing first_time (what you incorrectly refer to as "calling").
Instead, you should either overwrite first_time by reassigning datetime.now() to it, or you should declare a new variable and assign datetime.now() to it.
# Overwriting & outputting:
# first_time = datetime.now()
# Declaring a new (updated) value (what I'll use in the example):
second_time = datetime.now()
# Outputting:
print('first_time: %s\nsecond_time: %s' % (str(first_time), str(second_time)))
You can define as follows:
def now():
return datetime.datetime.now().strftime('%d.%m.%Y %H:%M:%S')
use the definition in the following way:
print('{}'.format(now()))
Doing sample code for Unit Test in Python with Hypothesis module.
Wrote simple getTimeDelta function to get time difference between two dates.
Want to write Unit Test of the getTimeDelta function. Used hypothesis modules to get multiple datetime values.
Question is that:
1. How to I pass different data type values i.e. time1 is str
and time2 is datetime without writing multiple functions?
checking only datatype of return value, not actual result is correct or not. How to do that?
How to check data types of items, of result tuple? assertIsInstance
Code:
import unittest
from hypothesis import given
from hypothesis import strategies as st
import datetime
from dateutil.parser import parse as time_parse
def getTimeDelta(time1, time2):
try:
if isinstance(time1, str):
time1 = time_parse(time1)
if isinstance(time2, str):
time2 = time_parse(time2)
return (time1 - time2, {"message": ""})
except Exception as err:
return (False, {"message": "Exception {}".format(err)})
class TestTimeDeltaCalc(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestTimeDeltaCalc, self).__init__(*args, **kwargs)
self.utils = Utils()
#given(st.datetimes(), st.datetimes())
def test_time_delta(self, time1, time2):
time_delta = getTimeDelta(time1, time2)
if time_delta[0] is False:
self.assertIsInstance(time_delta[0], bool)
else:
self.assertIsInstance(time_delta[0], datetime.timedelta)
self.assertIsInstance(time_delta[1], dict)
#given(st.text(), st.text())
def test_time_delta(self, time1, time2):
time_delta = getTimeDelta(time1, time2)
if time_delta[0] is False:
self.assertIsInstance(time_delta[0], bool)
else:
self.assertIsInstance(time_delta[0], datetime.timedelta)
self.assertIsInstance(time_delta[1], dict)
if __name__ == '__main__':
unittest.main()
Edit 01:
We can fix #Question1 by hypothesis.strategies.one_of(*args), link
one_of is exactly the right approach.
There are many ways to test properties (see eg this article), but the easiest here is probably a "test oracle": just compare the result to a known-good implementation! Otherwise, you could eg. check that the timedelta is negative/0/positive if time1 is lt/eq/gt time2 - this is basically a lower-resolution oracle.
Your assertIsInstance calls look like they'd work to me.
I'm working on a calendar via Python's HTMLCalendar and Django. The functions I'm using to input data into the calendar are showing up as unbound, and therefore not working.
Here's the calendar code:
from www.wednesday.models import Event
import calendar
e = Event()
class EventCal(calendar.HTMLCalendar):
def formatday(self, day, weekday):
if day == 0:
return '<td class="noday"> </td>' # Day outside month
if day == e.dd():
return '<td class="%s">%d</p>%s</td>' % (self.cssclasses[weekday], day, e.link(), e.res())
else:
return '<td class="%s">%d</td>' % (self.cssclasses[weekday], day)
class rendCal:
c = EventCal(calendar.SUNDAY)
Here's my models.py:
from django.db import models
class Event(models.Model):
Restaurant = models.CharField(max_length=200)
LinkURL = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
DateDay = models.IntegerField(max_length=2)
def dd(self):
return '%i' % self.DateDay
def link(self):
return '%s' % self.LinkURL
def res(self):
return '%s' % self.Restaurant
And lastly, my views.py:
from django.shortcuts import render_to_response
import www.wednesday.models
from www.wednesday.cal import rendCal
import datetime as dt
def calendar(request):
now = dt.datetime.now()
cal = rendCal.c.formatmonth(now.year, now.month)
return render_to_response('cal.html', {'calendar': cal})
Everything works except for the functions from Event that are called inside the EventCal class.
Obviously I'm quite new at this.
Okay, #Marcin asked for an error, this is what I'm seeing, also I corrected the capitalization.
TypeError at /calendar/
unbound method dd() must be called with Event instance as first argument (got nothing instead)
cal.py in formatday, line 9
The environment variables in EventCal from Event are showing up blank, I'm pretty sure that's why I'd been getting the needs int not str error. When I change e.dd() to a static number, it returns everything but e.link() and e.res().
dd() is a method of an instance of the class.
You call it like this:
e = Event()
x = e.dd()
You can't apply dd to Event itself.
I am not sure what exactly you are trying to do, so I am not sure how you need to modify your code.
In formatday you have:
if day == 0:
but also:
if day == Event.dd():
and Event.dd() returns a string.
So, is day an int or a string?
This has come up several times recently and I'd like to deal with it better than I have been: I have a series of attributes that I'm cross referencing between an object and a dictionary. If the value is different between them, I want to set the object.attribute to the dictionary['attribute'] value. I also want to keep track of what's getting changed.
Now, my first thought is to just use an if else statement for every attribute, but after writing a few of these it's apparent that I'm re-writing the same code again and again. There has to be a DRY way to do this, where I specify only the parts that are changing every time, and then loop through all the attributes.
In production code, there are 15 different attributes, but my example below will just use 2 for simplicity. I have some idea about how to do this in a clever way, but I'm missing the final step of actually setting the object.attribute equal to the dictionary['attribute'] value.
# Simulated data setup - not under my control IRL
class someClass:
def __init__(self, name, version):
self.name = name
self.version = version
objA = someClass('Test1','1.1')
dictA = {'name':'Test1','revision':'1.2'}
# My code below
# option 1 - a series of for loops
def updateAttributesSimple(obj, adict, msg):
if obj.name == adict['name']:
msg.append('Name is the same')
else:
msg.append('Name was updated from %s to %s' % (obj.name, adict['name']))
obj.name = adict['name']
if obj.version == adict['revision']:
msg.append('Version is the same')
else:
msg.append('Version was updated from %s to %s' % (obj.version, adict['revision']))
obj.version = adict['revision']
# option 2 - trying to be clever about this
def updateAttributesClever(obj, adict, msg):
attributeList = (('Name', obj.name, adict['name']),
('Version', obj.version, adict['revision']))
for valTuple in attributeList:
if valTuple[1] == valTuple[2]:
msg.append('%s is the same' % (valTuple[0]))
else:
msg.append('%s was updated from %s to %s' % (valTuple[0], valTuple[1], valTuple[2]))
# code to set valTuple[1] = valTuple[2] goes here, but what is it?
# valTuple[1] = valTuple[2] attempts to set the desired value to a string, rather than the attribute of obj itself
msg = ['Updating Attributes simple way:']
updateAttributesSimple(objA, dictA, msg)
print '\n\t'.join(msg)
#reset data
objA = someClass('Test1','1.1')
dictA = {'name':'Test1','revision':'1.2'}
msg = ['Updating Attributes clever way:']
updateAttributesClever(objB, dictB, msg)
print '\n\t'.join(msg)
The idea being that this way, whenever I need to add another attribute, I can just update the list of attributes being inspected and the rest of the code is already written. What's the Pythonic way to accomplish this?
setattr() is what you're looking for:
attributeList = (('Name', 'name', 'name'),
('Version', 'version', 'revision'))
for title, obj_attribute, dict_key in attributeList:
obj_value = getattr(obj, obj_attribute)
adict_value = adict[dict_key]
if obj_value == adict_value:
msg.append('%s is the same' % (obj_value))
else:
msg.append('%s was updated from %s to %s' % (title, obj_value, adict_value))
setattr(obj, obj_attribute, adict_value)
This should work for your:
class X(object):
def __init__(self):
self.a = 1
self.b = 2
x = X()
d = dict()
d['a'] = 1
d['b'] = 3
def updateAttributes(obj,dic):
def update(name):
val = dic[name]
if getattr(obj,name)==val:
print name,"was equal"
else:
print "setting %s to %s" % (name,val)
setattr(obj,name,val)
for name in ['a','b']:
update(name)
updateAttributes(x,d)
print x.a
print x.b
You might want to think about creating a function which can take an arbitrary object and convert the dictionary of name/value pairs into something more meaningful. It's not strictly a "Python" strategy but something that is fairly easy to do in Python because of its support of closures and how it treats objects under the hood:
def checkUpdates( obj ):
def updated( dictionaryPrevious, msg ):
for name, value in dictionaryPrevious.items():
if( obj.__dict__[name] == value ):
msg.append('Name is the same')
else:
msg.append(name + 'has been changed!')
obj.__dict__[name] = value
return updated
I am making one assumption, the names in the dictionary always correspond to the object variables. If they're not the same you'll need to make a mapping.
edit:
() => [] and object => obj. thanks guys. Sometimes you go from one language to a few others and it all gets muddled.
A couple of answers are close, but to handle that fact that the name of the key in the dict don't match the corresponding object's attribute name, you'll need some way to handle that. This can be easily done by adding yet another dictionary mapping the names of keys in the dict to the names of the object's attributes.
class someClass:
def __init__(self, name, version):
self.name = name
self.version = version
objA = someClass('Test1','1.1')
dictA = {'name':'Test1','revision':'1.2'}
keymap = {'name':'name', 'revision':'version'}
def updateAttributesGeneric(obj, adict, key2attr, msg):
for key, value in adict.iteritems():
attrname = key2attr[key]
if getattr(obj, attrname) == value:
msg.append('%s is the same' % attrname)
else:
msg.append('%s has been changed' % attrname)
setattr(obj, attrname, adict[key])
msg = ['Updating Attributes:']
updateAttributesGeneric(objA, dictA, keymap, msg)
print '\n\t'.join(msg)
# Updating Attributes:
# name is the same
# version has been changed
How do I set the timezone of a datetime instance that just came out of the datastore?
When it first comes out it is in UTC. I want to change it to EST.
I'm trying, for example:
class Book( db.Model ):
creationTime = db.DateTimeProperty()
When a Book is retrieved, I want to set its tzinfo immediately:
book.creationTime.tzinfo = EST
Where I use this example for my EST object
However I get:
attribute 'tzinfo' of 'datetime.datetime' objects is not writable
I've seen a number of answers that recommend pytz and python-dateutil, but I really want an answer to this question.
datetime's objects are immutable, so you never change any of their attributes -- you make a new object with some attributes the same, and some different, and assign it to whatever you need to assign it to.
I.e., in your case, instead of
book.creationTime.tzinfo = EST
you have to code
book.creationTime = book.creationTime.replace(tzinfo=EST)
If you're receiving a datetime that's in EST, but doesn't have its tzinfo field set, use dt.replace(tzinfo=tz) to assign a tzinfo without modifying the time. (Your database should be doing this for you.)
If you're receiving a datetime that's in UDT, and you want it in EST, then you need astimezone. http://docs.python.org/library/datetime.html#datetime.datetime.astimezone
In the vast majority of cases, your database should be storing and returning data in UDT, and you shouldn't need to use replace (except possibly to assign a UDT tzinfo).
What you want is right there in the docs.
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
HOUR = timedelta(hours=1)
DSTSTART = datetime(1, 4, 1, 2)
DSTEND = datetime(1, 10, 25, 1)
def first_sunday_on_or_after(dt):
days_to_go = 6 - dt.weekday()
if days_to_go:
dt += timedelta(days_to_go)
return dt
class USTimeZone(tzinfo):
def __init__(self, hours, reprname, stdname, dstname):
self.stdoffset = timedelta(hours=hours)
self.reprname = reprname
self.stdname = stdname
self.dstname = dstname
def __repr__(self):
return self.reprname
def tzname(self, dt):
if self.dst(dt):
return self.dstname
else:
return self.stdname
def utcoffset(self, dt):
return self.stdoffset + self.dst(dt)
def dst(self, dt):
if dt is None or dt.tzinfo is None:
# An exception may be sensible here, in one or both cases.
# It depends on how you want to treat them. The default
# fromutc() implementation (called by the default astimezone()
# implementation) passes a datetime with dt.tzinfo is self.
return ZERO
assert dt.tzinfo is self
# Find first Sunday in April & the last in October.
start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year))
end = first_sunday_on_or_after(DSTEND.replace(year=dt.year))
# Can't compare naive to aware objects, so strip the timezone from
# dt first.
if start <= dt.replace(tzinfo=None) < end:
return HOUR
else:
return ZERO
now = datetime.now()
print now
print now.tzinfo
Eastern = USTimeZone(-5, 'Eastern', 'EST', 'EDT')
now_tz_aware = now.replace(tzinfo=Eastern)
print now_tz_aware
output:
2010-01-18 17:08:02.741482
None
2010-01-18 17:08:02.741482-05:00