0dff2f461fad1d3dc16350557208e6c153676346
[anna.git] / include / anna / time / internal / Timezone.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_time_internal_Timezone_hpp
10 #define anna_time_internal_Timezone_hpp
11
12
13 // Standard
14 #include <string>
15 #include <stdlib.h>
16 #include <iostream>
17
18 extern char *tzname[2];
19
20 //------------------------------------------------------------------------------
21 //---------------------------------------------------------------------- #define
22 //------------------------------------------------------------------------------
23
24
25 namespace anna {
26
27 namespace time {
28
29 class Timezone {
30
31   bool a_initialized;
32   std::string a_value;
33   bool a_unsetTZ;
34
35 public:
36
37   Timezone() { a_initialized = false; };
38   ~Timezone() {};
39
40
41   // sets
42   // pass NULL to unset
43   void set(const char *input) {
44     a_initialized = true;
45     a_value = input ? input : "";
46
47   //  /*
48   //    In many C libraries, TZ='' is equivalent to TZ='GMT0' or TZ='UTC0',
49   //    and that's the behavior you're observing. An unset TZ is equivalent
50   //    to a system-supplied default, typically the local time where the host
51   //    is physically located.
52   //  */
53   //  if (input && (a_value == "")) a_value="UTC0";
54
55     a_unsetTZ = !input;
56   }
57
58   Timezone & operator = (const Timezone &tz) {
59     if(this == &tz) return (*this);
60
61     a_initialized = tz.isInitialized();
62     a_value = tz.getValue();
63     a_unsetTZ = tz.unsetTZ();
64     return (*this);
65   }
66
67   // gets
68
69   // Operators
70
71   friend bool operator == (const Timezone & tz1, const Timezone & tz2) {
72     if(tz1.isInitialized() != tz2.isInitialized())
73       return (false);
74
75     if(tz1.unsetTZ())
76       return (tz2.unsetTZ());
77
78     return (tz1.getValue() == tz2.getValue());
79   }
80
81   friend bool operator != (const Timezone & tz1, const Timezone & tz2) {
82     return (!(tz1 == tz2));
83   }
84
85   // be careful: empty if unset
86   const std::string & getValue(void) const throw() {
87     return (a_value);
88   }
89
90
91   bool isInitialized(void) const throw() {
92     return (a_initialized);
93   }
94
95   //Unset is when getenv("TZ") returns NULL. Then, /etc/localtime used to be a copy or symlink to
96   // any of the /usr/share/zoneinfo available timezones.
97   bool unsetTZ(void) const throw() { return (a_unsetTZ); }
98
99   bool apply() const throw() {
100     //    http://stackoverflow.com/questions/5873029/questions-about-putenv-and-setenv
101     if(unsetTZ()) {
102       unsetenv("TZ");                                                             
103     }                                                                             
104     else {                                                                        
105       setenv("TZ", a_value.c_str(), 1 /* overwrite */);                              
106
107       /*
108       // If TZ has an invalid setting, tzset() uses GMT0:
109       // Check it:
110       tzset();
111       //std::cout << "tzname[0]: " << tzname[0] << std::endl;
112       //std::cout << "tzname[1]: " << tzname[1] << std::endl;
113       std::string tzname_1 = tzname[1];
114       bool success = (tzname_1 != "");
115       if (!success) std::cerr << "Invalid TZ '" << a_value << "'. Probably GMT0 is going to be used instead !" << std::endl;
116       return success;
117       */
118     }                                                                             
119
120     return true;
121   }
122
123   std::string asString() const throw() {
124     std::string result = getValue();
125     if (unsetTZ()) return "<TZ unset>";
126     if (result == "") return "<TZ empty>";
127     return result;
128   }
129 };
130
131
132 }
133 }
134
135 #endif
136