logo

drewdevault.com

[mirror] blog and personal website of Drew DeVault git clone https://hacktivis.me/git/mirror/drewdevault.com.git

Python-datetime-sucks.md (2958B)


  1. ---
  2. date: 2014-06-28
  3. # vim: tw=82
  4. title: Python's datetime sucks
  5. layout: post
  6. tags: [python]
  7. ---
  8. I've been playing with Python for about a year now, and I like pretty much
  9. everything about it. There's one thing that's really rather bad and really should
  10. not be that bad, however - date & time support. It's ridiculous how bad it is in
  11. Python. This is what you get with the standard datetime module:
  12. * The current time and strftime, with a reasonable set of properties
  13. * Time deltas with days, seconds, and microseconds and nothing else
  14. * Acceptable support for parsing dates and times
  15. What you don't get is:
  16. * Meaningful time deltas
  17. * Useful arithmetic
  18. Date and time support is a rather tricky thing to do and it's something that the
  19. standard library should support well enough to put it in the back of your mind
  20. instead of making you do all the work.
  21. We'll be comparing it to C# and .NET.
  22. Let's say I want to get the total hours between two `datetime`s.
  23. ```cs
  24. // C#
  25. DateTime a, b;
  26. double hours = (b - a).TotalHours;
  27. ```
  28. ```python
  29. # Python
  30. a, b = ...
  31. hours = (b - a).seconds / 60 / 60
  32. ```
  33. That's not so bad. How about getting the time exactly one month in the future:
  34. ```cs
  35. var a = DateTime.Now.AddMonths(1);
  36. ```
  37. ```python
  38. a = date.now() + timedelta(days=30)
  39. ```
  40. Well, that's not ideal. In C#, if you add one month to Janurary 30th, you get
  41. Feburary 28th (or leap day if appropriate). In Python, you could write a janky
  42. function to do this for you, or you could use the crappy alternative I wrote
  43. above.
  44. How about if I want to take a delta between dates and show it somewhere, like a
  45. countdown? Say an event is happening at some point in the future and I want to
  46. print "3 days, 5 hours, 12 minutes, 10 seconds left". This is distinct from the
  47. first example, which could give you "50 hours", whereas this example would give
  48. you "2 days, 2 hours".
  49. ```cs
  50. DateTime future = ...;
  51. var delta = future - DateTime.Now;
  52. Console.WriteLine("{0} days, {1} hours, {2} minutes, {3} seconds left",
  53. delta.Days,
  54. delta.Hours,
  55. delta.Minutes,
  56. delta.Seconds);
  57. ```
  58. ```python
  59. # ...mess of math you have to implement yourself omitted...
  60. ```
  61. Maybe I have a website where users can set their locale?
  62. ```cs
  63. DateTime a = ...;
  64. Console.WriteLine(a.ToString("some format string", user.Locale));
  65. ```
  66. ```python
  67. locale.setlocale(locale.LC_TIME, "sv_SE") # Global!
  68. print(time.strftime("some format string"))
  69. ```
  70. By the way, that Python one doesn't work on Windows. It uses system locales names
  71. which are different on Windows than on Linux or OS X. Mono (cross-platform .NET)
  72. handles this for you on any system.
  73. And a few other cases that are easy in .NET and not in Python:
  74. * Days since the start of this year
  75. * Constants like the days in every month
  76. * Is it currently DST in this timezone?
  77. * Is this a leap year?
  78. In short, Python's datetime module could really use a lot of fleshing out. This
  79. is common stuff and easy for a naive programmer to do wrong.