tzset.c 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. /* Provide tzset for systems that don't have it or for which it's broken.
  2. Copyright (C) 2001-2003, 2005-2007, 2009-2022 Free Software Foundation, Inc.
  3. This file is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This file is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>. */
  13. /* written by Jim Meyering */
  14. #include <config.h>
  15. /* Specification. */
  16. #include <time.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. void
  20. rpl_tzset (void)
  21. #undef tzset
  22. {
  23. #if defined _WIN32 && ! defined __CYGWIN__
  24. /* Rectify the value of the environment variable TZ.
  25. There are four possible kinds of such values:
  26. - Traditional US time zone names, e.g. "PST8PDT". Syntax: see
  27. <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset>
  28. - Time zone names based on geography, that contain one or more
  29. slashes, e.g. "Europe/Moscow".
  30. - Time zone names based on geography, without slashes, e.g.
  31. "Singapore".
  32. - Time zone names that contain explicit DST rules. Syntax: see
  33. <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03>
  34. The Microsoft CRT understands only the first kind. It produces incorrect
  35. results if the value of TZ is of the other kinds.
  36. But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to a value
  37. of the second kind for most geographies, or of the first kind in a few
  38. other geographies. If it is of the second kind, neutralize it. For the
  39. Microsoft CRT, an absent or empty TZ means the time zone that the user
  40. has set in the Windows Control Panel.
  41. If the value of TZ is of the third or fourth kind -- Cygwin programs
  42. understand these syntaxes as well --, it does not matter whether we
  43. neutralize it or not, since these values occur only when a Cygwin user
  44. has set TZ explicitly; this case is 1. rare and 2. under the user's
  45. responsibility. */
  46. const char *tz = getenv ("TZ");
  47. if (tz != NULL && strchr (tz, '/') != NULL)
  48. _putenv ("TZ=");
  49. /* On native Windows, tzset() is deprecated. Use _tzset() instead. See
  50. <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-tzset>
  51. <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset> */
  52. _tzset ();
  53. #else
  54. tzset ();
  55. #endif
  56. }