Date bug? receiving error only on certain dates - python

The following code gets the start of the week of a date argument:
weekstart = datetime.datetime.strptime(sys.argv[1], '%m/%d/%Y')
if weekstart.strftime('%A') != 'Sunday':
print "Start date should be a Sunday"
while weekstart.strftime('%A') != 'Sunday':
#weekstart = weekstart - datetime.timedelta(a)
a=a+1
print "Using %s as start date instead" %weekstart.strftime('%m/%d/%Y')
I receive the following error only when the date entered is 7/10/2012, 7/11/2012, 7/12/2012, or 7/13/2012:
while weekstart.strftime('%A') != 'Sunday':
ValueError: year=1899 is before 1900; the datetime strftime() methods require year >= 1900
What is wrong with this?

Yes, this is a bug in your concept. You are incorrectly incrementing a and decreasing weekstart by that a. So it does not go day by day, but by 1, 2, 3, 4,… days.
7/10/2012 is Tuesday. Substract 1 day…
7/9/2012 is Monday. Substract 2 days…
7/7/2012 is Saturday. Substract 3 days…
7/4/2012 is Wednesday. Substract 4 days…
6/30/2012 is Saturday. Substract 5 days…
6/25/2012 is Monday. Substract 6 days…
6/19/2012 is Tuesday. Substract 7 days, i.e. one week and the loop goes on faster and faster until the year 1899 when it breaks.
It means that if your first day is Tuesday, it will never reach Sunday this way.
It works for 7/11/2012 (and any Wednesday), it breaks for 7/12/2012 (and any Thursday), it breaks for 7/13/2012 (and any Friday), it works for 7/14/2012 (and any Saturday) and it works for 7/16/2012 (and any Monday) and of course it stops immediately for any Sunday.
But it is not what you want.
If you want to get the previous (or today's) Sunday for any day without loops, just use this:
weekstart = weekstart - datetime.timedelta((weekstart.weekday() - 6) % 7)
Or, if you want to avoid mathematics and use libraries (dateutil):
from dateutil import relativedelta
weekstart = weekstart + relativedelta.relativedelta(weekday=relativedelta.SU(-1))

Related

Python - Check every other week using if statement

I have the following if statement:
if date.weekday() != 0:
How can I change this if statement to check every other Monday (one day every other week)?
Thanks in advance for your help!
You post doesn't mention what language you're using. That would be useful to know!
At any rate, a function like weekday probably returns a number from 0-6, which isn't going to give you enough info.
Most languages have a function that turns a date into a millisecond value, typically milliseconds since 1970-01-01 00:00 UTC.
If you take such a value and divide it by 86400000 (number of milliseconds in a day), you get a day number. Day 0 (January 1, 1970) happens to be a Thursday.
In JavaScript, this day number can be obtained from a Date object like this:
let dayNum = Math.floor(someDate.getTime() / 86400000)
From this, dayNum % 7 gives you a number from 0-6 for Thursday through Wednesday. You can add an offset to change what 0 means. (dayNum + 4) % 7 produces 0-6 for Sunday through Saturday.
You want a 14-day cycle for every other week, so dayNum % 14 is what you need, and you then just have to decide which value from 0 to 13 represents your target dates.
Take any sample date that is one of your desired dates, compute the remainder value you get for that date, and then test for that value to be able to match any qualifying date.
Two caveats:
For dates before 1970, the % operator might produces negative numbers. Python is one of the few languages that doesn't do this.
The timezone offset from UTC might be important to your task. And if that's important, Daylight Saving Time changes and/or historical changes in UTC offset can complicate matters.
Python update:
Let's say this coming Monday (July 5, 2021) is one of the every-other-week days that you want. This:
date(2021, 7, 5).toordinal() % 14
...produces a value of 8. Every other Monday before or after will also be 8. The toordinal() method goes straight to a day number, without having to fuss with milliseconds, 86400000, or having to worry about timezone offsets.

Is the output week number string correct?

I'm trying to generate week number string using Python time module, considering week starts on Sunday.
If my interpretation of the official documentation is correct then this can be achieved by the following code:
import time
time.strftime("%U", time.localtime())
>> 37
My question is, is the above output correct? Shouldn't the output be 38 instead, considering the below details:
My timezone is IST (GMT+5:30)
import time
#Year
time.localtime()[0]
>> 2019
#Month
time.localtime()[1]
>> 9
#Day
time.localtime()[2]
>> 18
Yes, the output is correct. Week 1 started on January 6th, as that was the first Sunday in 2019. January 1st through 5th were week 0:
>>> time.strftime('%U', time.strptime("2019-1-1", "%Y-%m-%d"))
'00'
>>> time.strftime('%U', time.strptime("2019-1-6", "%Y-%m-%d"))
'01'
This is covered in the documentation:
All days in a new year preceding the first Sunday are considered to be in week 0.
You are perhaps looking for the ISO week date, but note that in this system the first day of the week is a Monday.
You can get the week number using that system with the datetime.date.isocalendar() method, or by formatting with %V:
>>> time.strftime("%V", time.localtime())
'38'
>>> from datetime import date
>>> date.today().isocalendar() # returns ISO year, week, and weekday
(2019, 38, 2)
>>> date.today().strftime("%V")
'38'
It's correct since you start counting from the first Sunday.
%U - week number of the current year, starting with the first Sunday as the first day of the first week
https://www.tutorialspoint.com/python/time_strftime.htm
It's correct. Since all days in a new year preceding the first Sunday are considered to be in week 0 (01/01 to 01/05), this week is the week 37.

Calculate Elapsed time in python in specific format

I am trying to write a program to determine the time and date corresponding to a elapsed number of seconds since 00: 00: 00 on 1 January 2016.
But i wanted my result in specific format.
i.e should be the corresponding hour (in military time), minute, second, day of the month, month name, year, and day of the week name (Sunday – Saturday).
for example,output should look like the following
23:59:32 2 January 2018 Tuesday
i tried to code this
import time
start = time.time()
#do something
end = time.time()
temp = end-start
print(temp)
hours = temp//3600
temp = temp - 3600*hours
minutes = temp//60
seconds = temp - 60*minutes
print('%d:%d:%d' %(hours,minutes,seconds))
But i could only get the hours, minutes and seconds part,
Is there any way i can get the month,year,and week name too ?
Also i'm trying to handle leap years too.since a leap year has 366 days with 29 days in February. Leap years are years that are evenly divisible by 4, with the exception of those evenly divisible by 100 but not 400.
To format a datetime you can use strftime().
import datetime
my_time = datetime.datetime(year=2018, month=1, day=2, hour=23, minute=59,second=32)
print (my_time.strftime("%X %-d %B %Y %A"))
If you want to change the format use this table for reference
You want to use the Datetime Module. Handling dates and times is trickier than it appears! That's why it's good that Python has datetime handling built-in. Datetime and timedelta objects account for leap years and leap seconds, and they handle operations like addition and subtraction 'intuitively'.
import datetime
def convert_seconds_since_jan_1(seconds):
JAN_1_2001 = datetime.datetime(year = 2001, month = 1, day = 1)
added_time = datetime.timedelta(seconds = seconds)
return (JAN_1_2001+added_time)
Getting the weekday is simply a matter of string formatting. Remember that weekdays are modulo 7!

Getting a date from a week number

I am trying to get a date based on a number of the week, but there are some annoyances.
The date.weekday() returns the day of the week where 0 in Monday and 6 is Sunday.
The %w directive of date.strftime() and date.strptime() uses the 0 for Sunday and 6 for Saturday.
This causes some really annoying issues when trying to figure out a date given a week number from date.weekday().
Is there a better way of getting a date from a week number?
EDIT:
Added the example.
import datetime
original_date = datetime.date(2014, 8, 24)
week_of_the_date = original_date.isocalendar()[1] # 34
day_of_the_date = original_date.isocalendar()[2] # 7
temp = '{0} {1} {2}'.format(*(2014, week_of_the_date, day_of_the_date-1))
date_from_week = datetime.datetime.strptime(temp, '%Y %W %w')
week_from_new_date = date_from_week.isocalendar()[1] # 35!!
EDIT 2:
I ultimately put the date stuff in the view (using jQuery UI), it has more consistent notions of weeks.
I think the Sunday vs. Monday distinction between weekday and strftime using %W is moot - you could use isoweekday to get those to line up, or %U in strftime if you wanted Sunday as the first day of the week. The real problem is that strftime, based on the underlying C function, determines the first week of the year differently than the ISO definition. With %W the docs say: " All days in a new year preceding the first Monday are considered to be in week 0". ISO calendars count the week containing the first Thursday as the first week, for reasons I do not understand.
Two ways I found to work with ISO weeks, either just getting datetime.date instances back or supporting a variety of operations, are:
this answer with a simple timedelta approach:
What's the best way to find the inverse of datetime.isocalendar()?
this third-party library: https://pypi.python.org/pypi/isoweek/

Get week number using date in python

Date is datetime.date(2013, 12, 30)
I am trying to get week number using
import datetime
datetime.date(2013, 12, 30).isocalendar()[1]
I am getting output as ,
1
Why i am not getting week number of last year , instead i am getting week number of current year?
Whats wrong i am doing here ?
You are doing nothing wrong, 2013/12/30 falls in week 1 of 2014, according to the ISO8601 week numbering standard:
The ISO 8601 definition for week 01 is the week with the year's first Thursday in it.
The Thursday in that week is 2014/01/02.
Other ways to explain the definition, from the same linked WikiPedia article:
It is the first week with a majority (four or more) of its days in January (ISO weeks start on Monday)
Its first day is the Monday nearest to 1 January.
It has 4 January in it. Hence the earliest possible dates are 29 December through 4 January, the latest 4 through 10 January.
It has the year's first working day in it, if Saturdays, Sundays and 1 January are not working days.
If you were looking for the last week number of a given year (52 or 53, depending on the year), I'd use December 28th, which is always guaranteed to be in the last week (because January 4th is always part of the first week of the next year):
def lastweeknumber(year):
return datetime.date(year, 12, 28).isocalendar()[1]
from datetime import date
from datetime import datetime
ndate='10/1/2016'
ndate = datetime.strptime(ndate, '%m/%d/%Y').strftime('%Y,%m,%d')
print('new format:',ndate)
d=ndate.split(',')
wkno = date(int(d[0]),int(d[1]),int(d[2])).isocalendar()[1]
print(wkno)
manually or read a date to a string and get the week number, play around with different formats.

Categories