Skip to content

Conversation

mroeschke
Copy link
Member

@mroeschke mroeschke commented Nov 8, 2017

closes #12805
closes #12806

  • tests added / passed
  • passes git diff upstream/master -u -- "*.py" | flake8 --diff
  • whatsnew entry

I am not sure what locales are available on the CI machines, but the test will run all available locales.

@jreback
Copy link
Contributor

jreback commented Nov 8, 2017

need to add month_name to nat docstrings generation

-
-
- :attr:`Timestamp.month_name`, :attr:`DatetimeIndex.month_name`, and :attr:`Series.dt.month_name` are now available (:issue:`12805`)
- ``month_name` and ``weekday_name`` attributes will now return locale aware values (:issue:`12806`)
Copy link
Contributor

Choose a reason for hiding this comment

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

move the 2nd point to bug fix; only mention weekday_name and use attr (as u did for month_name)


# GH 12806
@pytest.mark.parametrize('time_locale', tm.get_locales())
def test_datetimeindex_accessors(self, time_locale):
Copy link
Contributor

Choose a reason for hiding this comment

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

can u split out the month_name and weekday_name to a separate test
skip if number of locales is 0

can then check that we don’t skip on build where we should have a locales defined

@jreback jreback added Compat pandas objects compatability with Numpy or Python functions Enhancement Datetime Datetime data dtype labels Nov 8, 2017
@mroeschke
Copy link
Member Author

Added month_name as a property to NaT, moved whatsnew updates, and moved name accessor tests to their own function with a skip if no locales are available.

@@ -22,7 +22,7 @@ Other Enhancements
^^^^^^^^^^^^^^^^^^

- :meth:`Timestamp.timestamp` is now available in Python 2.7. (:issue:`17329`)
-
- :attr:`Timestamp.month_name`, :attr:`DatetimeIndex.month_name`, and :attr:`Series.dt.month_name` are now available (:issue:`12805`)
Copy link
Contributor

Choose a reason for hiding this comment

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

actually move these to 0.22, we can't backport this as you are using some of the new timeseries stuff

@codecov
Copy link

codecov bot commented Nov 10, 2017

Codecov Report

Merging #18164 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #18164      +/-   ##
==========================================
+ Coverage    91.4%    91.4%   +<.01%     
==========================================
  Files         163      163              
  Lines       50064    50069       +5     
==========================================
+ Hits        45759    45768       +9     
+ Misses       4305     4301       -4
Flag Coverage Δ
#multiple 89.21% <100%> (+0.02%) ⬆️
#single 40.39% <100%> (-0.04%) ⬇️
Impacted Files Coverage Δ
pandas/core/indexes/datetimes.py 95.48% <100%> (+0.1%) ⬆️
pandas/io/gbq.py 25% <0%> (-58.34%) ⬇️
pandas/core/frame.py 97.8% <0%> (-0.1%) ⬇️
pandas/io/formats/format.py 96.01% <0%> (ø) ⬆️
pandas/core/generic.py 95.72% <0%> (ø) ⬆️
pandas/core/config_init.py 98.34% <0%> (ø) ⬆️
pandas/core/groupby.py 92.04% <0%> (+0.01%) ⬆️
pandas/plotting/_converter.py 65.2% <0%> (+1.81%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ca737ac...6f39578. Read the comment docs.

@codecov
Copy link

codecov bot commented Nov 10, 2017

Codecov Report

Merging #18164 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #18164      +/-   ##
==========================================
+ Coverage   91.69%   91.69%   +<.01%     
==========================================
  Files         150      150              
  Lines       49043    48997      -46     
==========================================
- Hits        44968    44929      -39     
+ Misses       4075     4068       -7
Flag Coverage Δ
#multiple 90.07% <100%> (ø) ⬆️
#single 41.94% <12.5%> (+0.12%) ⬆️
Impacted Files Coverage Δ
pandas/core/indexes/datetimes.py 95.57% <100%> (-0.02%) ⬇️
pandas/core/indexes/base.py 96.45% <0%> (-0.22%) ⬇️
pandas/core/internals.py 95.53% <0%> (-0.01%) ⬇️
pandas/io/formats/format.py 96.25% <0%> (-0.01%) ⬇️
pandas/core/generic.py 95.88% <0%> (-0.01%) ⬇️
pandas/core/config_init.py 100% <0%> (ø) ⬆️
pandas/core/indexes/range.py 95.7% <0%> (ø) ⬆️
pandas/core/groupby.py 92.31% <0%> (+0.17%) ⬆️
pandas/io/formats/style.py 96.22% <0%> (+0.18%) ⬆️
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5f271eb...d97f43b. Read the comment docs.

@@ -94,7 +94,7 @@ Bug Fixes
Conversion
^^^^^^^^^^

-
- Bug in :attr:`Timestamp.weekday_name` and :attr:`DatetimeIndex.weekday_name` not returning locale aware values (:issue:`12806`)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we should this as a bug, it is rather an API change as we deliberately returned non-locale dependent values.

(and to be honest, I am also not sure that I really like locale-dependent return values)

Copy link
Contributor

Choose a reason for hiding this comment

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

we could add an additonal accessor, e.g. weekday_name_for_locale? (hate adding things, but I agree that this might not be only desirable in some cases).

Copy link
Member Author

Choose a reason for hiding this comment

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

We could turn weekday_name and month_name into functions that can accept a locale argument and default it to 'en_US.UTF8'? I think that would be clean, but it would definitely be an API change.

Copy link
Contributor

Choose a reason for hiding this comment

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

hmm, that's an idea. we could could make new ones weekday_names() (and then just deprecate weekday_name

@jorisvandenbossche
Copy link
Member

@mroeschke We could turn weekday_name and month_name into functions that can accept a locale argument and default it to 'en_US.UTF8'? I think that would be clean, but it would definitely be an API change.

@jreback hmm, that's an idea. we could could make new ones weekday_names() (and then just deprecate weekday_name

That's an option. Another option is to leave it as is but to clearly document in those attributes how to get your locale dependent names. Eg it would be nice that the following would work:

In [26]: import calendar

In [27]: dt = pd.date_range('2016-01-01', periods=10, freq='10D')

In [28]: dt.weekday
Out[28]: Int64Index([4, 0, 3, 6, 2, 5, 1, 4, 0, 3], dtype='int64')

In [29]: dt.weekday.map(calendar.day_name)
...
TypeError: '_localized_day' object is not callable

(the problem here is that calendar.day_name is some kind of mapping (it has __getitem__) but not really)

This works:

In [32]: pd.Series(dt.weekday).map({i: calendar.day_name[i] for i in range(7)})
Out[32]: 
0       Friday
1       Monday
2     Thursday
3       Sunday
4    Wednesday
5     Saturday
6      Tuesday
7       Friday
8       Monday
9     Thursday
dtype: object

(second issue is that Index.map apparently does not work with dict, while Series.map does)

But I think both issues could be solved to make this easier.

@jorisvandenbossche
Copy link
Member

(On the other hand, such a pointer in the docstring is certainly less discoverable than a month_name method, I just in doubt this is worth it adding yet another method ..)

@jorisvandenbossche
Copy link
Member

Index.map dict issue is reported here: #13517

@mroeschke
Copy link
Member Author

I'll summarize the proposals and add an additional one:

  1. Default to the user's system's locale (this PR)
  2. Create a new function (would personally prefer .day_name(locale='en_US.UTF8') harmonizing with calendar.day_name)
  3. Default to English locale and enhance the docs with a locale recipe
  4. Utilize pandas.set_option and add something like mode.time_locale, defaulting to the English locale.

I think 4) would be a nice option to maintain the existing behavior and minimize altering existing methods. Otherwise I think I'd prefer 3) over 2) (I realize the Pandas API is already large).

What do you guys think @jreback @jorisvandenbossche?

@jreback
Copy link
Contributor

jreback commented Nov 10, 2017

so I actually like renaming weekday_name -> day_name regardless here for consistency.

  1. is interesting

I wonder how common the need to look things up in different locales is, if its not that common (guess), then this makes sense

  1. appeals as well (talking about the argument for the locale in the function call)

@mroeschke
Copy link
Member Author

I decided to implement a day_name(time_locale=None) and month_name(time_locale=None) method that can accept a locale argument. Wanted to run the implementation by you guys.

Also, should I got ahead and also depreciate the .weekday_name attribute in this PR?

@jreback
Copy link
Contributor

jreback commented Nov 23, 2017

I decided to implement a day_name(time_locale=None) and month_name(time_locale=None) method that can accept a locale argument. Wanted to run the implementation by you guys.

that sounds good

Also, should I got ahead and also depreciate the .weekday_name attribute in this PR?

yes this is also ok

@mroeschke
Copy link
Member Author

Sorry for being idle on this PR. Rebased, and added the day_name() and month_name() methods to Timestamp and DatetimeIndex

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

can you also deprecate weekday_name (in favor of day_name)


count = len(dtindex)
out = np.empty(count, dtype=object)

if field == 'weekday_name':
_dayname = np.array(['Monday', 'Tuesday', 'Wednesday', 'Thursday',
Copy link
Contributor

Choose a reason for hiding this comment

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

move (and import from) ccalendar

'friday', 'saturday', 'sunday'],
dtype=np.object_)
else:
with set_locale(time_locale, locale.LC_TIME):
Copy link
Contributor

Choose a reason for hiding this comment

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

this function (the locale conversion of the names) should be in ccalandar.pyx
just have a function which takes the locale (default None), so this is much simpler here

@@ -320,7 +325,32 @@ class NaTType(_NaT):
# nan methods
weekday = _make_nan_func('weekday', datetime)
isoweekday = _make_nan_func('isoweekday', datetime)
month_name = _make_nan_func('month_name', # noqa:E128
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

make this a named parameter

@@ -42,8 +42,13 @@ _nat_scalar_rules[Py_GE] = False
def _make_nan_func(func_name, cls):
Copy link
Contributor

Choose a reason for hiding this comment

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

make doc an optional parameter doc

@mroeschke
Copy link
Member Author

mroeschke commented Jan 13, 2018

Created get_locale_names in ccalendar.pyx that provides localized day and month names, _make_missing_value_func to replace _make_nan_func and _make_nat_func, and added deprecation to weekday_name

Although, I am not sure how to add a deprecation warning to DatetimeIndex.weekday_name since the method is pre-generated with _field_accessor

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

need tests that catch the deprecation warning

@property
def weekday_name(self):
"""
.. depreciated:: 0.23.0
Copy link
Contributor

Choose a reason for hiding this comment

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

deprecated

@@ -342,6 +327,37 @@ def test_datetimeindex_accessors(self):
assert dates.weekofyear.tolist() == expected
assert [d.weekofyear for d in dates] == expected

# GH 12806
@pytest.mark.skipif(not tm.get_locales(), reason='No available locales')
@pytest.mark.parametrize('time_locale', tm.get_locales())
Copy link
Contributor

Choose a reason for hiding this comment

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

this should still test for locale is None

@@ -1686,7 +1688,7 @@ def freq(self, value):
weekday_name = _field_accessor(
'weekday_name',
'weekday_name',
"The name of day in a week (ex: Friday)\n\n.. versionadded:: 0.18.1")
"The name of day in a week (ex: Friday)\n\n.. depreciated:: 0.23.0")
Copy link
Contributor

Choose a reason for hiding this comment

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

deprecated

Copy link
Contributor

Choose a reason for hiding this comment

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

need to show a deprecation warning for this as well

Copy link
Contributor

Choose a reason for hiding this comment

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

nvm i see this below

@@ -202,6 +202,8 @@ Other Enhancements
- ``Resampler`` objects now have a functioning :attr:`~pandas.core.resample.Resampler.pipe` method.
Previously, calls to ``pipe`` were diverted to the ``mean`` method (:issue:`17905`).
- :func:`~pandas.api.types.is_scalar` now returns ``True`` for ``DateOffset`` objects (:issue:`18943`).
- :meth:`Timestamp.month_name`, :meth:`DatetimeIndex.month_name`, and :meth:`Series.dt.month_name` are now available (:issue:`12805`)
- :meth:`Timestamp.day_name` and :meth:`DatetimeIndex.day_name` are now available to return day names with a specified locale (:issue:`12806`)
Copy link
Contributor

Choose a reason for hiding this comment

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

need an entry in Deprecated section

@@ -13,6 +13,9 @@ cimport numpy as np
from numpy cimport int64_t, int32_t
np.import_array()

import locale
from pandas.util.testing import set_locale
from strptime import LocaleTime
Copy link
Contributor

Choose a reason for hiding this comment

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

move these imports inside get_locale_names

days = dict(enumerate(ccalendar.DAYS_FULL))
else:
names = ccalendar.get_locale_names('f_weekday', time_locale)
days = dict(enumerate(names))
Copy link
Contributor

Choose a reason for hiding this comment

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

move the dict(enumerate after the if (eg do it once)

months = dict(enumerate(ccalendar.MONTHS_FULL))
else:
names = ccalendar.get_locale_names('f_month', time_locale)
months = dict(enumerate(names))
Copy link
Contributor

Choose a reason for hiding this comment

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

same

@jreback
Copy link
Contributor

jreback commented Feb 25, 2018

rebase on master

@mroeschke mroeschke force-pushed the add_localtime branch 2 times, most recently from 616665a to 565b5b6 Compare February 26, 2018 01:58
@mroeschke
Copy link
Member Author

Rebased on master and addressed your comments @jreback. Looks like a travis build timed out.

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

can you update the test that hits Series.dt.day_name (you have to add the new methods and remove the old one), in the series tests

@@ -199,3 +208,27 @@ cpdef int32_t get_day_of_year(int year, int month, int day) nogil:

day_of_year = mo_off + day
return day_of_year


cpdef get_locale_names(object name_type, object time_locale=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

only needs to be cdef unless called elsewhere

from pandas.util.testing import set_locale

with set_locale(time_locale, locale.LC_TIME):
locale_names = getattr(LocaleTime(), name_type)
Copy link
Contributor

Choose a reason for hiding this comment

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

you can just return this directly, no need to have a variable locale_names

@@ -85,7 +85,8 @@ def build_field_sarray(ndarray[int64_t] dtindex):

@cython.wraparound(False)
@cython.boundscheck(False)
def get_date_name_field(ndarray[int64_t] dtindex, object field):
def get_date_name_field(ndarray[int64_t] dtindex, object field,
object time_locale=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

rename to locale

@@ -96,23 +97,37 @@ def get_date_name_field(ndarray[int64_t] dtindex, object field):
pandas_datetimestruct dts
int dow

Copy link
Contributor

Choose a reason for hiding this comment

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

instead of using _dayname, _monthname, use cdef names ndarray[object]

month_name : string
""")
day_name = _make_nan_func('day_name', # noqa:E128
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

can you added versionadded 0.23 to these

expected_months = calendar.month_name[1:]

# GH 11128
dti = DatetimeIndex(freq='D', start=datetime(1998, 1, 1),
Copy link
Contributor

Choose a reason for hiding this comment

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

can you add a NaT here

@pytest.mark.skipif(not tm.get_locales(), reason='No available locales')
@pytest.mark.parametrize('time_locale', tm.get_locales() + [None])
def test_datetime_name_accessors(self, time_locale):
if time_locale is None:
Copy link
Contributor

Choose a reason for hiding this comment

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

add a comment what you are setting here

for day, name, eng_name in zip(range(4, 11),
expected_days,
english_days):
# Test Monday -> Sunday
Copy link
Contributor

Choose a reason for hiding this comment

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

can you move this comment to near the GH issue number


# GH 12805
dti = DatetimeIndex(freq='M', start='2012', end='2013')
# Test January -> December
Copy link
Contributor

Choose a reason for hiding this comment

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

same, move this up

Copy link
Contributor

Choose a reason for hiding this comment

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

add a NaT here

# GH 17354
assert data.weekday_name == expected
# Test .weekday_name, .day_name(), .month_name
Copy link
Contributor

Choose a reason for hiding this comment

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

test with NaT

@mroeschke
Copy link
Member Author

I believe I addressed everything

  • Testing NaT
  • Moved/added comments to tests
  • Added tests for Series.dt.*name
  • Added versionadded notes
  • reused get_name_date_field in Timestamp
  • renamed time_locale to locale

"""
Given a int64-based datetime index, return array of strings of date
name based on requested field (e.g. weekday_name)
"""
cdef:
Py_ssize_t i, count = 0
ndarray[object] out
ndarray[object] out, name
pandas_datetimestruct dts
Copy link
Contributor

Choose a reason for hiding this comment

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

should be names

"""
warnings.warn("`weekday_name` is deprecated and will be removed in a "
"future version. Use `day_name` instead",
DeprecationWarning)
Copy link
Contributor

Choose a reason for hiding this comment

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

can u have this call day_name

@mroeschke mroeschke force-pushed the add_localtime branch 2 times, most recently from 006ac9e to dbbfbe7 Compare February 28, 2018 19:04
@mroeschke
Copy link
Member Author

Changed name to names, and used the day_name method for weekday_name. All green

@jreback jreback added this to the 0.23.0 milestone Mar 1, 2018
Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

very small comments, also needs a rebase. ping on green.

@@ -581,6 +581,8 @@ These can be accessed like ``Series.dt.<property>``.
Series.dt.round
Series.dt.floor
Series.dt.ceil
Series.dt.month_name
Copy link
Contributor

Choose a reason for hiding this comment

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

if weekday_name is anywhere here can you remove

@@ -262,6 +262,8 @@ class DatetimeIndex(DatelikeOps, TimelikeOps, DatetimeIndexOpsMixin,
to_pydatetime
to_series
to_frame
Copy link
Contributor

Choose a reason for hiding this comment

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

if weekday_name is here can u remove

@jreback
Copy link
Contributor

jreback commented Mar 1, 2018

@jorisvandenbossche @TomAugspurger lgtm. if any final comments.

Fix localiztion of months

Add series test and whatsnew notes

Modify test and lint

Add Timestamp rst

Address comments

Lint, move whatsnew, remove hardcoded Monday, check that get_locale is None

create functions instead of attributes

Fix white space

Modify tests

Lint

Rebase and add depreciation message

Deprecate weekday_name, create localizing function in ccalendar.pyx

clean up imports

Address user comments

Try to address ci issues

Rebase and adjust tests

Move some imports to top of file, remove dup implimention of day_name in fields

Fix failing test

allow path to accept weekday_name as well

address review

address review missed files

fix typo and call internal method

Fix lint

modify pytest param for appvoyer

fix more appvoyer tests

Remove weekday_name availability
@mroeschke
Copy link
Member Author

Removed doc instances of weekday_name and all green (minus a Travis timeout)

@jreback jreback merged commit 607910b into pandas-dev:master Mar 4, 2018
@jreback
Copy link
Contributor

jreback commented Mar 4, 2018

thanks @mroeschke nice patch!

@mroeschke mroeschke deleted the add_localtime branch March 5, 2018 05:44
@jreback
Copy link
Contributor

jreback commented Mar 5, 2018

@mroeschke a number of deprecation warnings need catching.
also these should be FutureWarning and not DeprecationWarning. can you do a followup.

  /home/travis/build/pandas-dev/pandas/pandas/tests/indexes/datetimes/test_misc.py:274: DeprecationWarning: `weekday_name` is deprecated and will be removed in a future version. Use `day_name` instead
    assert ts.weekday_name == eng_name

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Compat pandas objects compatability with Numpy or Python functions Datetime Datetime data dtype Enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ENH: Use LocaleTime for date_field_name output ENH: add month_name to DatetimeIndex and .dt
4 participants