views:

287

answers:

4

Hi there,

I've been writing a time converter to take the systems time_t and convert it into human readable date/time. Oh, and this is my second python script ever. We'll leave that fact aside and move on.

The full script is hosted here.

Writing converters for the year and month were fairly easy, but I've hit a serious brick wall trying to get the day working. As you can see, I've been trying to brute-force my way all the way from 1970 to today. Unfortunately, the day comes out as -105.

Does anyone know of a better way to do it, or a way to fix up what I have attempted here? It's currently 3:30 AM, so it's quite possible I'm missing something obvious.

Sorry, I forgot to note that I'm doing this manually in order to learn python. Doing it via date functions defeats the purpose, unfortunately.

+2  A: 

You could do it either with time.strftime:

>>> import time
>>> time.strftime('%Y %B %d')
'2009 September 18'

or with datetime.date.strftime:

>>> import datetime
>>> datetime.date.today().strftime('%Y %B %d')
'2009 September 18'
SilentGhost
+6  A: 

Why not use:

from datetime import datetime
the_date = datetime.fromtimestamp(the_time)
print(the_date.strftime('%Y %B %d'))

The datetime module handles all the edge cases -- leap years, leap seconds, leap days -- as well as time zone conversion (with optional second argument)

dcrosta
it's `fromtimestamp`
SilentGhost
thanks -- silly typos.
dcrosta
changed print to print() -- print is a function in Python 3
dcrosta
While this is the 'correct' answer to my question, I'm not doing this to make a working clock! I'm doing this to learn python, so shortcut functions like this rather defeat the purpose of the exercise. Thanks for answering, though!
Ripdog
One of the joys of learning Python is learning what you don't need to implement yourself! The standard library is fairly comprehensive, and there are many third-party modules available at PyPi. May also want to check out http://diveintopython.org/
dcrosta
See also http://diveintopython3.org/ for a revised Python 3.0 version.
dcrosta
+1  A: 

(I'm assuming you do this to learn Python, so I'll point out the errors in your code).

>>> years = SecondsSinceEpoch / 31540000

Nonononono. You can't do that. Some years have 31536000 seconds, others have 31622400 seconds.

>>> if calendar.isleap(yeariterator) == True:

You don't need to test if a true value is true. :-) Do:

>>> if calendar.isleap(yeariterator):

Instead.

Also change:

>>> yeariterator = 1969
>>> iterator = 0
>>> while yeariterator < yearsfordayfunction:
>>>     yeariterator = yeariterator + 1

To:

for yeariterator in range(1970, yearsfordayfunction):

That will also fix your error: You don't stop until AFTER 2009, so you get the answer -105, because there is 105 days left of the year.

And also, there's not much point in calculating month by month. Year by year works fine.

    for yeariterator in range(1970, yearsfordayfunction):
            if calendar.isleap(yeariterator) == True:
                    days = days - 366
            else:
                    days = days - 365

And an indent of 8 spaces is a lot. 4 is more common.

Also, I'd calculate year and day of year in one method, instead of doing it twice.

def YearDay():
    SecondsSinceEpoch = int(time.time())
    days = SecondsSinceEpoch // 86400 # Double slash means floored int.
    year = 1970
    while True:
            if calendar.isleap(year):
                    days -= 366
            else:
                    days -= 365
            year += 1
            if calendar.isleap(year):
                    if days <= 366:
                            return year, days
            else:
                    if days <= 365:
                            return year, days


def MonthDay(year, day):
    if calendar.isleap(year):
            monthstarts = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]
    else:
            monthstarts = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365]

    month = 0
    for start in monthstarts:
            if start > day:
                    return month, day - monthstarts[month-1] + 1
            month += 1
Lennart Regebro
Thanks, this is exactly what I was looking for!A few points i'm not sure about, though:1. The GetDays() function was actually supposed to get the day of the month. :( I had it originally iterate through the months until `days <= 31: return days`. This is obviously a shitty method, Do you have any suggestions for a better one?2. Does the indent size actually matter? I had it at 8 for readability, but if it causes issues, then I'm happy to reduce it.3. How do I deal with a function returning two values?
Ripdog
No, indent size doesn't matter, but I think it's gets more readable at 4 spaces. You use a function returning two values like you send them: year, days = YearDays()Making a method that returns the month and day from the year and day is quite simple, and needs no iteration, so this makes for less iteration and faster code. Looping until days <= 31 doesn't work either, because not all months are 31 days long.I added an example month method too.
Lennart Regebro
Eh, although calculating the month without iteration was possible, it wasn't entirely trivial. So I added a method that was, but uses loops.
Lennart Regebro
A: 

I'll also point out something odd in the code you posted:

    try:
            SecondsSinceEpoch = time.time()
    except IOError:
            Print("Unable to get your system time!")

1.) Why would time.time() raise an IOError? As far as I know it's impossible for that function to raise an error, it should always return a value.

2.) Print should be print.

3.) Even if time.time did raise an IOError exception, you are swallowing the exception, which you probably don't want to do. The next line requires SecondsSinceEpoch to be defined, so that will just raise another (more confusing) exception.

lost-theory
Completely true. I had no clue if it could spit out an error, and which error it would spit out if it did. I just put that there because I thought I was writing a "future proof" program. :PHubris, I know.
Ripdog