Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Review]: Clean up parse_time API #887

Merged
merged 14 commits into from Aug 25, 2014
Merged

[Review]: Clean up parse_time API #887

merged 14 commits into from Aug 25, 2014

Conversation

gunner272
Copy link
Contributor

I added the small ability to parse international time seconds(time elapsed in seconds from 1958,1,1) to time.parse_time function ,Please provide feedback

Thank You

@derdon
Copy link
Member

derdon commented Mar 3, 2014

I have a déjà vu …

@gunner272
Copy link
Contributor Author

I closed the previous request
#870
Opened a new one ,with the same changes but removing the unwarranted ones

"""
if isinstance(time_string, datetime):
return time_string
elif isinstance(time_string, tuple):
return datetime(*time_string)
elif tai and ( isinstance( time_string, int) or isinstance( time_string, float)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix the formatting to: elif tai and isinstance(time_string, int) or isinstance(time_string, float):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing the above was clashing with other unit test cases

def test_parse_time_int():
>       assert parse_time(765548612.0) == datetime(2003, 4, 5, 12, 23, 32)
E       assert datetime.datetime(1982, 4, 5, 12, 23, 32) == datetime.datetime(2003, 4, 5, 12, 23, 32)
E        +  where datetime.datetime(1982, 4, 5, 12, 23, 32) = parse_time(765548612.0)
E        +  and   datetime.datetime(2003, 4, 5, 12, 23, 32) = datetime(2003, 4, 5, 12, 23, 32)

time/tests/test_time.py:24: AssertionError

@coveralls
Copy link

Coverage Status

Coverage increased (+0.02%) when pulling 4ca1f61 on gunner272:tai into 76ae390 on sunpy:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.01%) when pulling 4ea62c6 on gunner272:tai into 76ae390 on sunpy:master.

"""
if isinstance(time_string, datetime):
return time_string
elif isinstance(time_string, tuple):
return datetime(*time_string)
elif tai and isinstance( time_string, int) or tai and isinstance( time_string, float) :
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question to the most pythonists! Would it be consider a bad practice to put this as:

elif (tai and isinstance( time_string, int)) or (tai and isinstance (time_string, float)):

? This makes it, at least to me, easier to read.

But, in any case, could we not just do this as:

elif tai and (isinstance( time_string, int)) or isinstance (time_string, float)):

I believe in this case the () are essential, otherwise we could get True by just having time_string as float.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and has a higher priority than or. The syntax of Python is defined in a way that (expr) is the same as expr, the parentheses only determine the precedence level. (those two things are very common in all languages I know that contain some form of and/&& and parentheses to denote the precedence level). Another important thing to know is that for boolean algebra the distributive law holds: A AND (B OR C) = A AND B OR A AND C.

To answer your question @dpshelio: keeping these facts in mind, the first example tai and isinstance(time_string, int) or tai and isinstance(time_string, float) (I removed unnecessary parens) is equivalent to tai and (isinstance(time_string, int) or isinstance(time_string, float))

@gunner272
Copy link
Contributor Author

I agree with both of you ,from a personal opinion I prefer the style with the parenthesis,gives an easier to understand code

@derdon
Copy link
Member

derdon commented Mar 5, 2014

I didn't share my opinion. I just explained which expressions are equivalent. Now to share my opinion: with only two extra expressions (those that check the type) I don't have any strong feelings. But especially if it gets more, I'm in favor of the solution which is of the form tai and (A or B or C or …) because it obeys DRY (don't repeat yourself) and makes the code more extensible and maintainable.

@gunner272
Copy link
Contributor Author

I am a bit confused,should I change it back?

@derdon
Copy link
Member

derdon commented Mar 6, 2014

Well, at least you should follow PEP 8 and also remove unnecessary parens. The other thing is subjective for such a short line.

@dpshelio
Copy link
Member

dpshelio commented Mar 9, 2014

Thanks @derdon for the explanation and your point of view. I also prefer the:

tai and (A or B or C ...) 

approach.

@gunner272, could you make the changes suggested in the docstring and change the comparison from above obeying DRY.

@@ -23,6 +23,16 @@ def test_parse_time_tuple():
def test_parse_time_int():
assert parse_time(765548612.0) == datetime(2003, 4, 5, 12, 23, 32)
assert parse_time(1009685652.0) == datetime(2010, 12, 30, 4, 14, 12)

def test_parse_time_tai():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, could you insert a commented line or docstring in here pointing us to the source you've used to get the TAI values? webpage, algorithm, etc..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about the resource because these values were manually calculated by me,I believe they would be correct ,but please feel free to cross check the calculations

@gunner272
Copy link
Contributor Author

@dpshelio ,Could you please put a line note on the docstring I should edit

@dpshelio
Copy link
Member

@gunner272 I think is failing because the GOES api gone by the wind....

@aringlis
Copy link
Member

What's the status of this, now that the GOES lightcurve source has been fixed by #942?

@Cadair
Copy link
Member

Cadair commented May 12, 2014

Can you change this so that it would look more like this:

parse_time(time, format='tai')

can you also add format='utime' which I think is the current default. Also can someone please suggest a docstring that explains what the hell utime actually is?!

like this:
http://docs.astropy.org/en/stable/time/index.html

@aringlis
Copy link
Member

Copied from 'anytim.pro': UTIME - Utime format, Real*8 seconds since 1-jan-79

@Cadair
Copy link
Member

Cadair commented May 12, 2014

oohhhhh solarsoft ... bite me

@aringlis
Copy link
Member

👍

@ayshih
Copy link
Member

ayshih commented May 19, 2014

This PR will be blocked until an outstanding issue with leap seconds is resolved.

Now resolved


.. todo::
add ability to parse tai (International Atomic Time seconds since
Jan 1, 1958)
"""
if isinstance(time_string, datetime):
return time_string
elif isinstance(time_string, tuple):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would be better if it tested for all iterables that are not strings rather than just tuples.

there is a is_iterable function in astropy somewhere.

@ehsteve
Copy link
Member

ehsteve commented May 19, 2014

Btw, astropy.time does seem to handle leap seconds. See http://astropy.readthedocs.org/en/latest/time/.

@Cadair
Copy link
Member

Cadair commented Jun 2, 2014

@gunner272 Something has upset things. Looks like the API has changed in a non-backwards compatible way.

specifically I think that it no longer assumes 'utime' if a float is passed in. (https://travis-ci.org/sunpy/sunpy/jobs/26442840#L1351)

I suggest two things,

  1. I like that it dosen't understand floats by default, so the best thing to do is fix the places where parse_time is called for utime.
  2. Make the error nicer if a float is passed when the time_format is a string.

@gunner272
Copy link
Contributor Author

@Cadair : like the change above if isinstance(time_string, datetime) or time_format == 'datetime':
shouldn't this also be changed to
time_format == 'utime' or ( isinstance(time_string, int) or isinstance(time_string, float) )

@Cadair
Copy link
Member

Cadair commented Jun 2, 2014

@gunner272 that is the simple solution, that doesn't change the API. I suppose for now that is the best bet.

Can you make sure that behaviour is documented, that it assumes floats are 'utime'?

@coveralls
Copy link

Coverage Status

Coverage increased (+0.64%) when pulling ee5bb21 on gunner272:tai into b37e155 on sunpy:master.

return time_string
elif isinstance(time_string, tuple):
return datetime(*time_string)
elif isinstance(time_string, int) or isinstance(time_string, float):
elif time_format == 'utime' or ( isinstance(time_string, int) or isinstance(time_string, float) ) :
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elif time_format == 'utime' or isinstance(time_string, (int, float)): does the same.

@Cadair Cadair modified the milestone: 0.5 Jun 6, 2014
@Cadair Cadair added the [Review] label Jun 6, 2014
@Cadair Cadair changed the title Clean up parse_time API [Review]: Clean up parse_time API Jun 6, 2014

time_string : [ int, float, time_string, datetime ]
Date to parse which can be either time_string, int, datetime object.
format : [ basestring, utime, datetime ]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be time_format, right? This doc should also define each of the possibilities (such as what is utime).

@Cadair Cadair removed this from the 0.5 milestone Jun 12, 2014


Note:
If time_string is an instance of float, then it is assumed to be in unix time format.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be "assumed to be utime" right?

@Cadair
Copy link
Member

Cadair commented Jul 14, 2014

👍

@@ -256,18 +260,15 @@ def day_of_year(time_string):
time_diff = time - datetime(time.year, 1, 1, 0, 0, 0)
return time_diff.days + time_diff.seconds / SECONDS_IN_DAY + 1


def break_time(t='now'):
def break_time(t=None, time_format=''):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this None not be 'now'?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it should, good spot.

@aringlis
Copy link
Member

👍

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.1%) when pulling 40c2f19 on gunner272:tai into 57ba719 on sunpy:master.

@Cadair
Copy link
Member

Cadair commented Aug 4, 2014

@ehsteve
Copy link
Member

ehsteve commented Aug 25, 2014

👍

ehsteve added a commit that referenced this pull request Aug 25, 2014
[Review]: Clean up `parse_time` API
@ehsteve ehsteve merged commit 806ba36 into sunpy:master Aug 25, 2014
@dpshelio dpshelio removed the Needs Review Needs reviews before merge label Apr 23, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants