views:

157

answers:

4

Hello,

I am working in a limited environment developing a python script.

My issue is I must be able to accomplish datetime addition and subtractions.

For example I get the following string:

"09/10/20,09:59:47-16"

Which is formatted as year/month/day,hour:minute:second-ms.

How would I go about adding 30 seconds to this number in Python? I can't use anything more than basic addition and subtraction and string parsing functions.

+2  A: 

You are doing math in different bases. You need to parse the string and come up with a list of values, for example (year, month, day, hour, minute, second), and then do other-base math to add and subtract. For example, hours are base-24, so you need to use modulus to perform the calculations. This sounds suspiciously like homework, so I won't go into any more detail :)

Jeff Ober
This is the approach I'm taking. It actually isn't homework (although in college I have had similar obnoxious assignments). It's just a very under-developed Python platform. The base math gets annoying when you start looking at months and how they have different numbers of days in them, heaven forbid you take into account leap-years.
Andrew Robinson
+1  A: 

For completeness, datetime.datetime.strptime and datetime.timedelta are included in default python distribution.

from datetime import datetime, timedelta

got = "09/10/20,09:59:47-16"

dt = datetime.strptime(got, '%y/%m/%d,%H:%M:%S-%f')
dt = dt + timedelta(seconds=30)
print dt.strftime('%y/%m/%d,%H:%M:%S-%f')

prints exactly

09/10/20,10:00:17-160000

Docs here.

nosklo
read the question
Ravi
@Ravi: The question was edited - I'm keeping my answer for reference and completeness - it is the sane way anyone without artificial restrictions would use.
nosklo
+2  A: 

The easiest way to perform date arithmetic is to not actually perform that arithmetic on the dates, but to do it to a simpler quantity.

Typically, that simpler quantity is the number of seconds since a certain epoch. Jan 1, 1970 works out nicely. Knowing the epoch, and the number of days in each month, and which years are leap years, you can convert from this "number of seconds" representation to a date string pretty easily (if not slowly in the naive version).

You will also need to convert the date string back to the simpler representation. This is again, not too hard.

Once you have those two functions, arithmetic is simple. Just add or subtract the amount of time to/from your "number of seconds" representation. Then convert back to a date string.

With all that said, I hope this is a homework assignment, because you absolutely should not be writing your own date handling functions in production code.

Frank Krueger
I agree. DateTime is just an obnoxious mess. However I'm developing on a platform lacking these functions.
Andrew Robinson
But DateTime contains knowledge beyond you or me. It being a mess (in your opinion) is not sufficient enough reason to not use it.
Frank Krueger
Not having it available is a sufficient reason not to use it
foosion
Sorry I was unclear. Physical dates and times are obnoxious messes. DateTime libraries make sense of the mess, using the knowledge beyond you and me.
Andrew Robinson
A: 

Here's my solution to the problem:

year = int(s[0:2])
month = int(s[3:5])
day = int(s[6:8])
hour = int(s[9:11])
minute = int(s[12:14])
second = int(s[15:17])

amount_to_add = 30
second = second + amount_to_add
days_in_month = 30
if(month == 1 or month == 3 or month == 5 or month ==7 or month ==  8 or month == 10 or         month == 12):
    days_in_month = 31
if(month == 2):
    days_in_month = 28
if ((((year%4 == 0) and (year%100 != 0)) or (year%400 == 0)) and month == 2):
    days_in_month = 29

if(second > 60):
    minute = minute + second/60
    second = second%60
if(minute > 60):
    hour = hour + minute/60
    minute = minute%60
if(hour >24):
    day = day + hour/60
    hour = hour%24
if(day > days_in_month):
    month = month + day/days_in_month
    day = day%days_in_month
if(month > 12):
    year = year + month/12
    month = month%12

Kind of a kludge but it gets the job done.

Andrew Robinson
I think you need to change your comparison logic to `>= 60` or `> 59` since once it gets to 60, that really means the 0th second of the next minute (repeat for min, hour, and month). Your current logic won't cascade correctly if `second == 30`.
Erich Mirabal
@Erich "repeat for min, hour, and month": Second and min should never == 60 and hour should never == 24, but month can == days_in_month
foosion
how about using `month in (1,3,5,7,8,31):`
gnibbler
seconds _can_ be 60!, ask Oracle http://suitablyflip.com/suitably_flip/2009/01/y2k9-leap-second-thwacks-oracle.html
gnibbler
@foosion: you are pseudo-right. `month` can equal `12`, but not `days_in_month` as you wrote it (I never mentioned `days` as that logic was correct). seconds, minutes, and hours are all 0-based; days and months are 1-based; hence the difference.
Erich Mirabal
(1) What is the maximum number of seconds to add? If it can cross TWO or more month boundaries, the existing code will fail; you need to calculate days_in_month for each month traversed, which means that you need to click the year over as well to allow for leap years. (2) Also fails when amount_to_add is negative. (3) Use `foo += delta` instead of `foo = foo + delta` (4) Use `minute // 60` instead of `minute / 60` (5) Avoid unnecessary parentheses in `if` ststements (6) your leap year calculation does major unnecessary work in non-February months -- indent it and remove ` and month == 2`
John Machin