iron-io / dockers

Uber tiny Docker images for all the things.
http://www.iron.io
MIT License
1.59k stars 139 forks source link

`strftime` doesn't work properly on Alpine Linux. #42

Closed mrmachine closed 6 years ago

mrmachine commented 8 years ago

OSX:

Python 2.7.10 (default, Aug 10 2015, 10:53:07) 
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> n = datetime.datetime.now()
>>> n.strftime('%I')
'04'
>>> n.strftime('%-I')
'4'

iron/python:2

Python 2.7.11 (default, Jan 23 2016, 12:34:14) 
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> n = datetime.datetime.now()
>>> n.strftime('%I')
'04'
>>> n.strftime('%-I')
''

The last line is an empty string (and no error) on Alpine Linux. This bug also affects the regular APK version of Python on Alpine Linux. Is there somewhere else/better that I should report this bug? I would love to use Alpine Linux, but we actually use this %-I in a strftime call in our app, so we can't.

treeder commented 8 years ago

This is an issue with Alpine Linux in general? strange. Is there anything on stackoverflow about it?

edsrzf commented 8 years ago

This appears to be an issue with musl's strftime implementation. I can write a C program that reproduces the problem.

Can anyone point to any documentation that says what the - in %-I is supposed to do? I can't seem to find it.

If this is behavior that musl is supposed to implement, then we should file an issue upstream. Otherwise, we'll have to look for workarounds.

mrmachine commented 8 years ago

This is all I could find about it: http://stackoverflow.com/a/28916983

Which quotes Glibc notes for strftime(3):

- (dash) Do not pad a numeric result string.
edsrzf commented 8 years ago

I emailed the musl mailing list and it looks like they're willing to add support for '-', '_', and '0'. I'll see about throwing a patch together.

In the meantime you'll need a workaround if you want to use the image, which should be as easy as:

n.strftime('%I').lstrip('0')

AlJohri commented 8 years ago

@edsrzf any update on this?

nikhilm commented 8 years ago

@AlJohri I don't think @edsrzf is actively working on this any more. That said, this was the only reply on the musl list - http://www.openwall.com/lists/musl/2016/03/29/11 The comment above documents a possible work around using lstrip. Have you tried it?

mrmachine commented 8 years ago

The workaround falls apart if you are using that formatting string as part of a larger pattern, not on its own (as seen above). And the workaround requires you to alter the source code of the Python application. When attempting to run a program on Alpine Linux, the vast majority of the source code is usually not under your direct control and having to fork it is a pain. When encountering an issue like this, it's also a huge red flag. If this simple thing doesn't work, and fails silently in a way that is not obvious to debug, what other subtle differences am I going to encounter? At that point, it's often much easier to simply abandon Alpine Linux and revert back to a more typical distro like Debian.

tobiasmcnulty commented 7 years ago

FYI, I believe that strftime in Alpine Linux does not respect the tzinfo of the datetime object, either. I had to make sure I had a datetime in local time and then .replace(tzinfo=None) to get the time to show up correctly, too.

zachliu commented 6 years ago

I can confirm this problem on python:3.6-alpine:

>>> from datetime import datetime
>>> dt = datetime(2018,6,4)
>>> dt.strftime("%m%-d%Y")
''

I ended up using python:3.6-slim instead. The size of the final image is 48MB larger (389MB vs 341MB) but I can live with that.

nicwolff commented 5 years ago

Fixed in either musl, alpine, or python by python:3.7-alpine:

$ docker run -it python:3.7-alpine
Python 3.7.4 (default, Jul 13 2019, 14:35:55) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> dt = datetime(2018,6,4)
>>> dt.strftime("%m%-d%Y")
'0642018'
blueyed commented 2 years ago

Just for reference: the issue is also fixed in python:3.6-alpine by now:

Status: Downloaded newer image for python:3.6-alpine
Python 3.6.15 (default, Nov 13 2021, 04:46:20) 
[GCC 10.3.1 20210424] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> dt = datetime(2018,6,4)
>>> dt.strftime("%m%-d%Y")
'0642018'