libanna.time refactoring
[anna.git] / source / time / Date.cpp
index fa6c8c3..e09a589 100644 (file)
@@ -60,312 +60,146 @@ using namespace anna::time;
 //------------------------------------------------------------------------- Date
 //******************************************************************************
 
-//------------------------------------------------------------------------------
-//----------------------------------------------------------------- Date::Date()
-//------------------------------------------------------------------------------
-Date::Date(const char * TzContext) {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "Default Constructor", ANNA_FILE_LOCATION));
-  time::sccs::activate();
-
-  if(!functions::initialized()) {
-    //anna::Logger::error("You should firstly invoke anna::time::functions::initialize() before using this module", ANNA_FILE_LOCATION);
-    //Perhaps former couldn't be written (no Logger initialize):
-    std::cout << std::endl << "Develop ERROR: you should firstly invoke anna::time::functions::initialize() before using time module" << std::endl;
-  }
-
-  a_local_tz = functions::getLocalTz();
-  a_work_tz = a_local_tz;
-  initialize(TzContext);
-};
-
-
-//------------------------------------------------------------------------------
-//----------------------------------------------------------------- Date::Date()
-//------------------------------------------------------------------------------
-Date::Date(const Date & d) {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "Copy constructor", ANNA_FILE_LOCATION));
-  time::sccs::activate();
-  *this = d;
-  a_local_tz = functions::getLocalTz();
-  a_work_tz = d.a_work_tz;
-};
-
-
-//------------------------------------------------------------------------------
-//---------------------------------------------------------------- Date::~Date()
-//------------------------------------------------------------------------------
-Date::~Date() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "~Date", ANNA_FILE_LOCATION));
-}
-
 // private:
 
-
 //------------------------------------------------------------------------------
-//-------------------------------------------------------------- Date::_putenv()
+//----------------------------------------------------------- Date::initialize()
 //------------------------------------------------------------------------------
-void Date::_putenv(const char * Tz) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "_putenv", ANNA_FILE_LOCATION));
-  TZ providedTz;
-
-  if(Tz)
-    providedTz.set(Tz);
-  else
-    providedTz = a_local_tz;
-
-  if(providedTz != a_work_tz) {
-    a_work_tz = providedTz;
-// Solaris no tiene el unsetenv, actualizamos directamente con putenv: "unset TZ", que es totalmente valido (*)
-//      if (a_work_tz.isUnset())
-//         unsetenv ("TZ");
-//      else
-    putenv((char *)a_work_tz.getShellAssignment().c_str());
-// (*)
-//      if (a_work_tz.isUnset())
-//         std::cout << "Unset" << std::endl;
-//      else
-//      {
-//         if (a_work_tz.isEmpty())
-//            std::cout << "Empty" << std::endl;
-//         else
-//            std::cout << a_work_tz.getValue() << std::endl;
-//      }
-//         std::cout << "Salida putenv poniendo " << a_work_tz.getAssignment().c_str() << ": " << putenv((char *)a_work_tz.getAssignment().c_str()) << std::endl;
-//         const char *kk = getenv("TZ");
-//         if (kk) std::cout << "getenv: " << kk << std::endl;
-//         else std::cout << "getenv: NULL" << std::endl;
-  }
+void Date::initialize(const char * TZ) throw() {
+  a_timestamp = ::time(NULL);
+  setTz(TZ);
 }
 
 
 //------------------------------------------------------------------------------
-//------------------------------------------------------- Date::set_tz_context()
+//-------------------------------------------------------------- Date::refresh()
 //------------------------------------------------------------------------------
-void Date::set_tz_context(const char * TzContext) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "set_tz_context", ANNA_FILE_LOCATION));
-  if(TzContext)
-    a_TZ_context.set(TzContext);
-  else
-    a_TZ_context = a_local_tz;
-
-  refresh_regarding_unix_timestamp(); // borns with timestamp and is based on new TZ value
-}
+void Date::refresh(void) throw() {
+  anna::Guard guard(a_mutex);
 
+  // Set current/programmed timezone
+  a_tz.apply();
 
-//------------------------------------------------------------------------------
-//------------------------------------------------------- Date::get_TZ_context()
-//------------------------------------------------------------------------------
-const TZ & Date::get_TZ_context(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "get_TZ_context", ANNA_FILE_LOCATION));
-  return (a_TZ_context);
+  // Rescue info:
+  struct tm *ptrTm = localtime(&a_timestamp);
+  a_tm = *ptrTm;
 }
 
 
-//------------------------------------------------------------------------------
-//---------------------------------------------------------- Date::_initialize()
-//------------------------------------------------------------------------------
-void Date::_initialize(const char * TzContext) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "_initialize", ANNA_FILE_LOCATION));
-  a_unix_timestamp = ::time(NULL);
-  set_tz_context(TzContext);  // This refresh all data with the asigned TZ
-}
 
+// public:
 
 //------------------------------------------------------------------------------
-//------------------------------------------------- Date::check_yyyymmddHHmmss()
+//----------------------------------------------------------------- Date::Date()
 //------------------------------------------------------------------------------
-void Date::check_yyyymmddHHmmss(const std::string & yyyymmddHHmmss)
-
-throw(anna::RuntimeException)
+Date::Date(const char *TZ) {
+  time::sccs::activate();
 
-{
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "check_yyyymmddHHmmss", ANNA_FILE_LOCATION));
-  // check 2038 effect: restrictive limit
-  if(yyyymmddHHmmss > _2K38_EFFECT_LIMIT) {  // ESTO NO LO COMPRUEBA mktime !!
-    throw anna::RuntimeException("Provided time/date is over 2K38 effect (19 January 2038, 03:14:07) !!", ANNA_FILE_LOCATION);
+  if(!functions::initialized()) {
+    std::cerr << std::endl << "Develop ERROR: you should firstly invoke anna::time::functions::initialize() before using time module" << std::endl;
   }
 
-  // check 14-digit length (i.e. "19741219100000")
-  int longitud = yyyymmddHHmmss.length();
-
-  if(longitud != 14) {
-    throw anna::RuntimeException("Provided time/date has not 14-digit length !!. Remember: 'yyyymmddHHmmss'", ANNA_FILE_LOCATION);
-  }
+  initialize(TZ);
+};
 
-  // All digits:
-  const char * ptr_cad = yyyymmddHHmmss.c_str();
 
-  for(register int k = 0; k < longitud; k++) {
-    if(!isdigit(ptr_cad[k])) {
-      throw anna::RuntimeException("Provided time/date only can contain digits !!. Remember: 'yyyymmddHHmmss'", ANNA_FILE_LOCATION);
-    }
-  }
+//------------------------------------------------------------------------------
+//---------------------------------------------------------------- Date::setTz()
+//------------------------------------------------------------------------------
+void Date::setTz(const char * TZ) throw() {
+  if (TZ) a_tz.set(TZ);
+  else a_tz = functions::getSystemTimezone(); 
 
-//   // Data range:
-//   int year, mon, mday, hour, min, sec;
-//   sscanf(ptr_cad, STRING_FORMAT_yyyymmddHHmmss, &year, &mon, &mday, &hour, &min, &sec);
-//   //year 2038 already checked
-//   if (mon < 1 || mon > 12)
-//      throw anna::RuntimeException("Month out of range (1-12) !!", ANNA_FILE_LOCATION);
-//   top_day = 31;
-//   if (mon == 2) top_day = 29/*28*/;
-//   if (mon == 4 || mon == 6 || mon == 9 || mon == 11) top_day = 30;
-//
-//   if (mday < 1 || mday > top_day)
-//      throw anna::RuntimeException(anna::functions::asString("Day out of range (1-%d) !!", top_day), ANNA_FILE_LOCATION);
-//   if (hour > 23)
-//      throw anna::RuntimeException("Hour out of range (0-23) !!", ANNA_FILE_LOCATION);
-//   if (min < 0 || min > 59)
-//      throw anna::RuntimeException("Minute out of range (0-59) !!", ANNA_FILE_LOCATION);
-//   if (sec < 0 || sec > 59)
-//      throw anna::RuntimeException("Second out of range (0-59) !!", ANNA_FILE_LOCATION);
+  refresh();
 }
 
 
 //------------------------------------------------------------------------------
-//------------------------------------- Date::refresh_regarding_unix_timestamp()
+//---------------------------------------------------- Date::setSystemTimezone()
 //------------------------------------------------------------------------------
-void Date::refresh_regarding_unix_timestamp(void) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "refresh_regarding_unix_timestamp", ANNA_FILE_LOCATION));
-  anna::Guard guard(a_mutex);
-  //anna::Guard<anna::Mutex> guard(a_mutex);
-  _putenv(get_TZ_context().getValue().c_str());
-  struct tm *ptrTm;
-  struct tm resTm;
-  //ptrTm = localtime_r(&a_unix_timestamp, &resTm); NO FUNCIONA BIEN EN LINUX!!
-  ptrTm = localtime(&a_unix_timestamp);
-  // OJO:
-  //   ctime() -> localtime() -> __tz_convert() -> __libc_lock_lock()
-  //   So, glibc does not guarantee the sane behavior when one uses ctime() in
-  //   signal handler.
-  //
-  //   Este problema puede ser de algún bug de la librería libc.so.6 de linux.
-  //   Recomiendan poner LD_ASSUME_KERNEL=2.4.1
-  // Otra solucion sera hacerlo MT-Safe con guardas
-  a_tm_struct = *ptrTm;
-  // Returns begining
-  _putenv(a_local_tz.getValue().c_str());
-  static char cad_aux[32];
-  sprintf(cad_aux, STRING_FORMAT_yyyymmddHHmmss,   1900 + a_tm_struct.tm_year, 1 + (a_tm_struct.tm_mon), a_tm_struct.tm_mday,
-          a_tm_struct.tm_hour, a_tm_struct.tm_min, a_tm_struct.tm_sec);
-  // Assignment:
-  _yyyymmddHHmmss = cad_aux;
+void Date::setSystemTimezone() throw() {
+  a_tz = functions::getSystemTimezone();
+  // Refresh the other data:
+  refresh();
 }
 
-// public
-
-// sets
-
 
 //------------------------------------------------------------------------------
-//----------------------------------------------------------- Date::initialize()
+//---------------------------------------------------------------- Date::store()
 //------------------------------------------------------------------------------
-void Date::initialize(const char * TzContext) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "initialize", ANNA_FILE_LOCATION));
-  _initialize(TzContext);
+void Date::store(const time_t & unixTimestamp) throw() {
+  a_timestamp = unixTimestamp;
+  // Refresh the other data:
+  refresh();
 }
 
 
 //------------------------------------------------------------------------------
-//--------------------------------------------------------- Date::setTzContext()
+//------------------------------------------------------------- Date::storeNtp()
 //------------------------------------------------------------------------------
-void Date::setTzContext(const char * TzContext) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "setTzContext", ANNA_FILE_LOCATION));
-  set_tz_context(TzContext);
+void Date::storeNtp(const unsigned int & ntpTimestamp) throw() {
+  a_timestamp = ntpTimestamp - TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970;
+  // Refresh the other data:
+  refresh();
 }
 
 
-
 //------------------------------------------------------------------------------
 //---------------------------------------------------------------- Date::store()
 //------------------------------------------------------------------------------
-void Date::store(const char* dateTimeAsStringFormat, const std::string & dateTimeAsString, const char * OriginTz)
+void Date::store(const struct tm &date, const char *TZ)
 
 throw(anna::RuntimeException)
 
 {
-  // Get equivalent 'tm':
-  struct tm TmOrigin;
-  memset(&TmOrigin, 0, sizeof(TmOrigin));
-
-  if(strptime(dateTimeAsString.c_str(), dateTimeAsStringFormat, &TmOrigin) == NULL) {
-    std::string msg("Error during strptime() conversion: '");
-    msg += dateTimeAsString;
-    msg += "' can't be interpreted as '";
-    msg += dateTimeAsStringFormat;
-    msg += "'";
-    throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
+  if (TZ) {
+    Timezone aux;
+    aux.set(TZ);
+    aux.apply();
+  }
+  else {
+    functions::getSystemTimezone().apply();
   }
 
-  store(TmOrigin, OriginTz);
-}
-
-
-void Date::store(const std::string & yyyymmddHHmmss, const char * OriginTz)
-
-throw(anna::RuntimeException)
-
-{
-  check_yyyymmddHHmmss(yyyymmddHHmmss);  // launch exception when format error (14 digits)
-  // Could be good, but not assing (perhaps 'strptime' could fail)
-// Limitaciones del 'strptime' usado por 'store(format, cadena)':
-// El formato directamente sacado de este interfaz ("%Y%m%d%H%M%S") no valida las fechas (meses 13, dias 32, etc),
-//  para ello hay que poner separadores en el formato (mucho más robusto). Aun asi, 'strptime' sigue "tragandose cosas"
-//  como por ejemplo segundos=60 (07:54:60 lo convierte a 07:55:00), y no comprueba los años bisiestos (de febrero traga
-//  29 dias siempre, aunque no traga 30)
-// Solucion, convertimos la cadena a otra con separadores para dar mayor robustez (aunque no es perfecto como se ha dicho):
-  int tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec;
-  sscanf(yyyymmddHHmmss.c_str(), STRING_FORMAT_yyyymmddHHmmss, &tm_year, &tm_mon, &tm_mday, &tm_hour, &tm_min, &tm_sec);
-  static char cad_aux[64];
-  sprintf(cad_aux, "%04d-%02d-%02d-%02d-%02d-%02d", tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec);
-  store(STRPTIME_FORMAT_yyyy_mm_dd_HH_mm_ss, cad_aux, OriginTz);
-}
-
-
-//------------------------------------------------------------------------------
-//---------------------------------------------------------------- Date::store()
-//------------------------------------------------------------------------------
-void Date::store(const struct tm & TmOrigen, const char * OriginTz)
-
-throw(anna::RuntimeException)
-
-{
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "store", ANNA_FILE_LOCATION));
-  _putenv(OriginTz);
   // Set '-1' on 'tm_isdst', or it could be an ambiguity on tranformation
   //  returning inexact timestamp. This setting force system to check the correct flag:
-  struct tm TmOrigen_isdst_menos1 = TmOrigen;
-  TmOrigen_isdst_menos1.tm_isdst = -1;
-  time_t unixTimestamp = mktime((struct tm*) & TmOrigen_isdst_menos1);
+  struct tm dateIsdst_1 = date;
+  dateIsdst_1.tm_isdst = -1;
+  time_t unixTimestamp = mktime((struct tm*) & dateIsdst_1);
 
   if(unixTimestamp == (time_t) - 1)
     throw anna::RuntimeException("Error during mktime() conversion !!", ANNA_FILE_LOCATION);
 
-  a_unix_timestamp = unixTimestamp;
+  a_timestamp = unixTimestamp;
+
   // Refresh the othr data:
-  refresh_regarding_unix_timestamp();
+  refresh();
 }
 
 
 //------------------------------------------------------------------------------
 //---------------------------------------------------------------- Date::store()
 //------------------------------------------------------------------------------
-void Date::store(const time_t & unixTimestamp) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "store unix timestamp", ANNA_FILE_LOCATION));
-  a_unix_timestamp = unixTimestamp;
-  // Refresh the other data:
-  refresh_regarding_unix_timestamp();
-}
+void Date::store(const std::string &stringDate, const char *TZ, const char *strptimeFormat)
+throw(anna::RuntimeException)
+{
+  if(strptimeFormat == NULL)
+    throw anna::RuntimeException("Invalid NULL strptimeFormat !!", ANNA_FILE_LOCATION);
 
+  // Get equivalent 'tm':
+  struct tm tmOrigin;
+  memset(&tmOrigin, 0, sizeof(tmOrigin));
 
-//------------------------------------------------------------------------------
-//------------------------------------------------------------- Date::storeNtp()
-//------------------------------------------------------------------------------
-void Date::storeNtp(const unsigned int & ntpTimestamp) throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "store ntp timestamp", ANNA_FILE_LOCATION));
-  a_unix_timestamp = ntpTimestamp - TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970;
-  // Refresh the other data:
-  refresh_regarding_unix_timestamp();
+  if(strptime(stringDate.c_str(), strptimeFormat, &tmOrigin) == NULL) {
+    std::string msg("Error during strptime() conversion: '");
+    msg += stringDate;
+    msg += "' can't be interpreted as '";
+    msg += strptimeFormat;
+    msg += "'";
+    throw anna::RuntimeException(msg, ANNA_FILE_LOCATION);
+  }
+
+  store(tmOrigin, TZ);
 }
 
 
@@ -373,65 +207,38 @@ void Date::storeNtp(const unsigned int & ntpTimestamp) throw() {
 //-------------------------------------------------------------- Date::operator=
 //------------------------------------------------------------------------------
 Date & Date::operator = (const Date & d) {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "operator=", ANNA_FILE_LOCATION));
   // avoid itself copy: i.e., Date a,b; a=&b; a=b; b=a;
   if(this == &d) return (*this);
 
-  a_TZ_context = d.get_TZ_context();
-  a_unix_timestamp = d.getUnixTimestamp();
-  a_tm_struct = d.getTm();
-  _yyyymmddHHmmss = d.yyyymmddHHmmss();
+  a_timestamp = d.getUnixTimestamp();
+  a_tz.set(d.getTz());
+  a_tm = d.getTm();
   return (*this);
 }
 
 
 // gets
 
-//------------------------------------------------------------------------------
-//--------------------------------------------------------- Date::getTzContext()
-//------------------------------------------------------------------------------
-const std::string & Date::getTzContext(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "getTzContext", ANNA_FILE_LOCATION));
-  return (a_TZ_context.getValue());
-}
-
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------- Date::yyyymmddHHmmss()
-//------------------------------------------------------------------------------
-const std::string & Date::yyyymmddHHmmss(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "yyyymmddHHmmss", ANNA_FILE_LOCATION));
-  return (_yyyymmddHHmmss);
-}
-
 
 //------------------------------------------------------------------------------
-//----------------------------------------------------- Date::getUnixTimestamp()
+//--------------------------------------------------------------- Date::getDay()
 //------------------------------------------------------------------------------
-const time_t & Date::getUnixTimestamp(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "getUnixTimestamp", ANNA_FILE_LOCATION));
-  return (a_unix_timestamp);
-}
+const char *Date::getDay(void) const throw() {
 
+  static const char *weekdayname[] = {"Sunday", "Monday", "Tuesday",
+    "Wednesday", "Thursday", "Friday", "Saturday"};
 
-//------------------------------------------------------------------------------
-//------------------------------------------------------ Date::getNtpTimestamp()
-//------------------------------------------------------------------------------
-unsigned int Date::getNtpTimestamp(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "getNtpTimestamp", ANNA_FILE_LOCATION));
-  unsigned int ntp_timestamp = a_unix_timestamp + TIMESTAMP_OFFSET_NTP1900_OVER_UNIX1970;
-  return (ntp_timestamp);
+  return weekdayname[a_tm.tm_wday];
 }
 
 
 //------------------------------------------------------------------------------
-//---------------------------------------------------------------- Date::getTm()
+//------------------------------------------------------- Date::yyyymmddHHmmss()
 //------------------------------------------------------------------------------
-const struct tm & Date::getTm(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "getTm", ANNA_FILE_LOCATION));
-
-
-  return (a_tm_struct);
+std::string Date::yyyymmddHHmmss(void) const throw() {
+  return anna::functions::asString("%04d%02d%02d%02d%02d%02d",
+     1900 + a_tm.tm_year, 1 + (a_tm.tm_mon), a_tm.tm_mday,
+     a_tm.tm_hour, a_tm.tm_min, a_tm.tm_sec);
 }
 
 
@@ -439,34 +246,16 @@ const struct tm & Date::getTm(void) const throw() {
 //------------------------------------------------------------- Date::asString()
 //------------------------------------------------------------------------------
 std::string Date::asString(void) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "asString", ANNA_FILE_LOCATION));
-  std::string trace;
-  static char cad_aux[256];
-  //bool differentContextAndLocalTZ = getTzContext() != a_local_tz.getValue();
-  sprintf(cad_aux, "%02d/%02d/%04d %02d:%02d:%02d",
-          //          yyyymmddHHmmss().c_str(),
-          getTm().tm_mday, 1 + (getTm().tm_mon), 1900 + getTm().tm_year,
-          getTm().tm_hour, getTm().tm_min, getTm().tm_sec);
-  trace = cad_aux;
-
-//   if (!(get_TZ_context().isUnset()))
-//      if (!(get_TZ_context().isEmpty()))
-//         { trace += " "; trace += get_TZ_context().getValue(); }
-  if(getTzContext() != ""/* && differentContextAndLocalTZ*/) { trace += " "; trace += getTzContext(); }
-
-  sprintf(cad_aux, ", isdst = %d [Unix Timestamp: %ld, Ntp Timestamp: %u]", getTm().tm_isdst, getUnixTimestamp(), getNtpTimestamp());
-  trace += cad_aux;
-
-//   if (!(a_local_tz.isUnset()))
-//      if (!(a_local_tz.isEmpty()))
-//         { trace += ", Local TZ = "; trace += a_local_tz.getValue(); }
-  if(a_local_tz.getValue() != "") {
-    //trace += differentContextAndLocalTZ ? ", Local TZ = ":", TZ Context = Local TZ = ";
-    trace += ", Local TZ = ";
-    trace += a_local_tz.getValue();
-  }
 
-  return (trace);
+  std::string result = anna::functions::asString("%s %02d/%02d/%04d %02d:%02d:%02d ", getDay(),
+                          getTm().tm_mday, 1 + (getTm().tm_mon), 1900 + getTm().tm_year,
+                          getTm().tm_hour, getTm().tm_min, getTm().tm_sec);
+  result += getTzAsString();
+  result += anna::functions::asString(", isdst = %d [Unix Timestamp: %ld, Ntp Timestamp: %u]", getTm().tm_isdst, getUnixTimestamp(), getNtpTimestamp());
+  result += ", System Timezone: ";
+  result += functions::getSystemTimezone().asString();
+
+  return result;
 }
 
 
@@ -474,21 +263,15 @@ std::string Date::asString(void) const throw() {
 //---------------------------------------------------------------- Date::asXML()
 //------------------------------------------------------------------------------
 anna::xml::Node* Date::asXML(anna::xml::Node* parent) const throw() {
-  //LOGMETHOD (TraceMethod tm ("anna::time::Date", "asXML", ANNA_FILE_LOCATION));
   //anna::xml::Node* result = parent->createChild("anna.time.Date");
-  //bool differentContextAndLocalTZ = getTzContext() != a_local_tz.getValue();
   parent->createAttribute("Date", anna::functions::asString("%02d/%02d/%04d", getTm().tm_mday, 1 + (getTm().tm_mon), 1900 + getTm().tm_year));
+  parent->createAttribute("Day", getDay());
   parent->createAttribute("Time", anna::functions::asString("%02d:%02d:%02d", getTm().tm_hour, getTm().tm_min, getTm().tm_sec));
-
-  if(getTzContext() != ""/* && differentContextAndLocalTZ*/) parent->createAttribute("TZContext", getTzContext());
-
+  parent->createAttribute("TZ", getTzAsString());
   parent->createAttribute("Isdst", (getTm().tm_isdst) ? "yes" : "no");
-//   parent->createAttribute("UnixTimestamp", anna::functions::asString("%lu seconds", getUnixTimestamp())); // unsigned long -> %lu
-//   parent->createAttribute("NtpTimestamp", anna::functions::asString("%u seconds", getNtpTimestamp())); // unsigned int -> %u
   parent->createAttribute("UnixTimestamp", anna::functions::asString((const int)getUnixTimestamp()));
   parent->createAttribute("NtpTimestamp", anna::functions::asString(getNtpTimestamp()));
-
-  if(a_local_tz.getValue() != "") parent->createAttribute(/*differentContextAndLocalTZ ? "LocalTZ":"TZContext=LocalTZ"*/"LocalTZ", a_local_tz.getValue());
+  parent->createAttribute("SystemTimezone", functions::getSystemTimezone().asString());
 
   return parent;
 }