libanna.time refactoring
[anna.git] / include / anna / time / internal / Timezone.hpp
diff --git a/include/anna/time/internal/Timezone.hpp b/include/anna/time/internal/Timezone.hpp
new file mode 100644 (file)
index 0000000..ed12614
--- /dev/null
@@ -0,0 +1,164 @@
+// ANNA - Anna is Not Nothingness Anymore
+//
+// (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
+//
+// https://bitbucket.org/testillano/anna
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: eduardo.ramos.testillano@gmail.com
+//          cisco.tierra@gmail.com
+
+
+#ifndef anna_time_internal_Timezone_hpp
+#define anna_time_internal_Timezone_hpp
+
+
+// Standard
+#include <string>
+#include <stdlib.h>
+#include <iostream>
+
+extern char *tzname[2];
+
+//------------------------------------------------------------------------------
+//---------------------------------------------------------------------- #define
+//------------------------------------------------------------------------------
+
+
+namespace anna {
+
+namespace time {
+
+class Timezone {
+
+  bool a_initialized;
+  std::string a_value;
+  bool a_unsetTZ;
+
+public:
+
+  Timezone() { a_initialized = false; };
+  ~Timezone() {};
+
+
+  // sets
+  // pass NULL to unset
+  void set(const char *input) {
+    a_initialized = true;
+    a_value = input ? input : "";
+
+  //  /*
+  //    In many C libraries, TZ='' is equivalent to TZ='GMT0' or TZ='UTC0',
+  //    and that's the behavior you're observing. An unset TZ is equivalent
+  //    to a system-supplied default, typically the local time where the host
+  //    is physically located.
+  //  */
+  //  if (input && (a_value == "")) a_value="UTC0";
+
+    a_unsetTZ = !input;
+  }
+
+  Timezone & operator = (const Timezone &tz) {
+    if(this == &tz) return (*this);
+
+    a_initialized = tz.isInitialized();
+    a_value = tz.getValue();
+    a_unsetTZ = tz.unsetTZ();
+    return (*this);
+  }
+
+  // gets
+
+  // Operators
+
+  friend bool operator == (const Timezone & tz1, const Timezone & tz2) {
+    if(tz1.isInitialized() != tz2.isInitialized())
+      return (false);
+
+    if(tz1.unsetTZ())
+      return (tz2.unsetTZ());
+
+    return (tz1.getValue() == tz2.getValue());
+  }
+
+  friend bool operator != (const Timezone & tz1, const Timezone & tz2) {
+    return (!(tz1 == tz2));
+  }
+
+  // be careful: empty if unset
+  const std::string & getValue(void) const throw() {
+    return (a_value);
+  }
+
+
+  bool isInitialized(void) const throw() {
+    return (a_initialized);
+  }
+
+  //Unset is when getenv("TZ") returns NULL. Then, /etc/localtime used to be a copy or symlink to
+  // any of the /usr/share/zoneinfo available timezones.
+  bool unsetTZ(void) const throw() { return (a_unsetTZ); }
+
+  bool apply() const throw() {
+    //    http://stackoverflow.com/questions/5873029/questions-about-putenv-and-setenv
+    if(unsetTZ()) {
+      unsetenv("TZ");                                                             
+    }                                                                             
+    else {                                                                        
+      setenv("TZ", a_value.c_str(), 1 /* overwrite */);                              
+
+      /*
+      // If TZ has an invalid setting, tzset() uses GMT0:
+      // Check it:
+      tzset();
+      //std::cout << "tzname[0]: " << tzname[0] << std::endl;
+      //std::cout << "tzname[1]: " << tzname[1] << std::endl;
+      std::string tzname_1 = tzname[1];
+      bool success = (tzname_1 != "");
+      if (!success) std::cerr << "Invalid TZ '" << a_value << "'. Probably GMT0 is going to be used instead !" << std::endl;
+      return success;
+      */
+    }                                                                             
+
+    return true;
+  }
+
+  std::string asString() const throw() {
+    std::string result = getValue();
+    if (unsetTZ()) return "<TZ unset>";
+    if (result == "") return "<TZ empty>";
+    return result;
+  }
+};
+
+
+}
+}
+
+#endif
+