4

Over here: https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior it says that %p displays AM / PM. It shows this

AM, PM (en_US);
am, pm (de_DE)

I'm not sure what de_DE is, but when I do %p using Django Rest Framework it shows AM and PM in capital letters. How do I change it so that am and pm are displayed in lowercase?

This is my DRF settings.py code where I edit the datetime format (might not be useful):

#added REST_FRAMEWORK
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DATETIME_FORMAT': "%b %d at %I:%M %p"
}
SilentDev
  • 20,997
  • 28
  • 111
  • 214

5 Answers5

8

Try changing '%p' to '%P'. Whether '%P' is supported depends on the 'strftime' function provided by the platform C library.

acw1668
  • 40,144
  • 5
  • 22
  • 34
  • 1
    +1 for recommending an un-documented feature. And for future readers, here's a link to `strftime` for [Perl](http://search.cpan.org/dist/TimeDate/lib/Date/Format.pm) and [PHP](http://php.net/manual/en/function.strftime.php), which specify `%p` and `%P`. And yes, upper/lower case is flipped. (`%p` = AM/PM & `%P` = am/pm) – aneroid Aug 11 '16 at 08:26
  • 1
    And if `%P` is not supported, like on Windows at least, the we get `ValueError: Invalid format string` – aneroid Aug 11 '16 at 08:29
4

I'm pretty sure that you cannot. The %p format code is the locale-specific "national representation of either "ante meridiem" (a.m.) or "post meridiem" (p.m.) as appropriate". de_DE is the generic German locale which is what defines the national representation which happens to be lowercase. The en_US locale has it defined in uppercase. Part of using functions like strftime is that they take care of the localization details for you.

The documentation does explicitly mention that the exact values are entirely locale specific:

Because the format depends on the current locale, care should be taken when making assumptions about the output value. Field orderings will vary (for example, “month/day/year” versus “day/month/year”), and the output may contain Unicode characters encoded using the locale’s default encoding (for example, if the current locale is ja_JP, the default encoding could be any one of eucJP, SJIS, or utf-8; use locale.getlocale() to determine the current locale’s encoding).

D.Shawley
  • 58,213
  • 10
  • 98
  • 113
4

en_US and de_DE are locales.

en_US = English US
de_DE = German Germany

In the en_US locale, AM/PM are uppercase whereas for the de_DE locale, it's shown in lower case.

You can use locale.setlocale(locale.LC_ALL, 'de_DE') to change your locale when you use time formatting and then revert it back after.

And to avoid issues with other date fields showing in the wrong order, like 'day,month,year' instead of the US-preferred 'month,day,year', when you use the time formatting options, make sure you specify all the fields and not one of the standard short/long time formats, since those will always be as per the locale. Example, %x:

%x    Locale’s appropriate date representation.    08/16/88 (None);
                                                   08/16/1988 (en_US);
                                                   16.08.1988 (de_DE)

However, doing this is not a good idea, since the month (for example) will appear in that language's name. So 'May' will appear as 'Mei' (affects both long and short forms).

A dirty workaround is to do a search and replace after the generating the timestring:

>>> datetime.strftime(datetime.today(), '%c %p').replace('AM', 'am').replace('PM', 'pm')
'08/10/16 10:37:49 am'
>>> datetime.strftime(datetime.today(), '%c %p').replace(' AM', ' am').replace(' PM', ' pm')
'08/10/16 10:39:19 am'

Again, not recommended since that will interfere with the timezone part where 'AM' and 'PM' occur - 'AMT', 'PMDT', 'GAMT'. If you're not displaying that or any other alphabets like for month, then it should be okay.

Community
  • 1
  • 1
aneroid
  • 12,983
  • 3
  • 36
  • 66
2

From the documentation you've linked:

Because the format depends on the current locale, care should be taken when making assumptions about the output value. Field orderings will vary (for example, “month/day/year” versus “day/month/year”), and the output may contain Unicode characters encoded using the locale’s default encoding (for example, if the current locale is js_JP, the default encoding could be any one of eucJP, SJIS, or utf-8; use locale.getlocale() to determine the current locale’s encoding).

So, I don't think you can do it with a simple formatting option without overriding locale settings which may irritate users if you end up overwriting their locale settings.

Two suggestions:

  • Use another formatting lib like Django's DateFormat ('a' will give you lowercase am/pm)
  • If you're using Linux that uses glibc then you can use "%P" as Python's strftime() is backended by C-lib's strftime()
avip
  • 1,445
  • 13
  • 14
0

Another option, albeit kinda klunky, is to store only the "AM/PM" portion of the timestamp to another variable, then simply do:

my_ampm = now.strftime("%p").lower()
Source Matters
  • 1,110
  • 2
  • 15
  • 35