diff --git a/ampel-firmware/co2_sensor.cpp b/ampel-firmware/co2_sensor.cpp
index 430b945575fe37c115351a741cf90caffa549e64..0850128e81a7d1826673a370f79eea8a348fc310 100644
--- a/ampel-firmware/co2_sensor.cpp
+++ b/ampel-firmware/co2_sensor.cpp
@@ -22,7 +22,7 @@ namespace sensor {
   uint16_t co2 = 0;
   float temperature = 0;
   float humidity = 0;
-  String timestamp = "";
+  char timestamp[23];
   int16_t stable_measurements = 0;
   uint32_t waiting_color = color::blue;
   bool should_calibrate = false;
@@ -168,7 +168,7 @@ namespace sensor {
 
     if (freshData) {
       // checkTimerDeviation();
-      timestamp = ntp::getLocalTime();
+      ntp::getLocalTime(timestamp);
       co2 = scd30.getCO2();
       temperature = scd30.getTemperature();
       humidity = scd30.getHumidity();
diff --git a/ampel-firmware/co2_sensor.h b/ampel-firmware/co2_sensor.h
index dd18bcf312048448ea665ad61b12ccb14b6f27c4..3a2b6f8976f1ffaab6cd024f2b2964a5ecfc564a 100644
--- a/ampel-firmware/co2_sensor.h
+++ b/ampel-firmware/co2_sensor.h
@@ -22,7 +22,7 @@ namespace sensor {
   extern uint16_t co2;
   extern float temperature;
   extern float humidity;
-  extern String timestamp;
+  extern char timestamp[23];
 
   void initialize();
   bool processData();
diff --git a/ampel-firmware/config.public.h b/ampel-firmware/config.public.h
index feb7f4e612f0fecb0b268f58b7b8fbdee04cb6ff..1ca67666cb3f76cb20ca1a9d03dc1b38d6bc3558 100644
--- a/ampel-firmware/config.public.h
+++ b/ampel-firmware/config.public.h
@@ -144,7 +144,7 @@
  */
 
 #  define NTP_SERVER "pool.ntp.org"
-#  define UTC_OFFSET_IN_SECONDS 3600 // [s] 3600 for UTC+1
+#  define UTC_OFFSET_IN_SECONDS 7200 // [s] 3600 for UTC+1, 7200 for UTC+1 and daylight saving time
 
 /**
  * Others
diff --git a/ampel-firmware/csv_writer.cpp b/ampel-firmware/csv_writer.cpp
index 2a7f462a4a750ed7565a8ff8318d6a608cbf12a0..7720e67493b4b3205296826686aac68454489842 100644
--- a/ampel-firmware/csv_writer.cpp
+++ b/ampel-firmware/csv_writer.cpp
@@ -6,7 +6,7 @@ namespace config {
 }
 namespace csv_writer {
   unsigned long last_written_at = 0;
-  String last_successful_write = "";
+  char last_successful_write[23];
 
 #if defined(ESP8266)
   /**
@@ -132,11 +132,11 @@ namespace csv_writer {
     return csv_file;
   }
 
-  void log(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
+  void log(const char *timestamp, const int16_t &co2, const float &temperature, const float &humidity) {
     led_effects::onBoardLEDOn();
     File csv_file = openOrCreate();
     char csv_line[42];
-    snprintf(csv_line, sizeof(csv_line), "%s;%d;%.1f;%.1f\r\n", timeStamp.c_str(), co2, temperature, humidity);
+    snprintf(csv_line, sizeof(csv_line), "%s;%d;%.1f;%.1f\r\n", timestamp, co2, temperature, humidity);
     if (csv_file) {
       size_t written_bytes = csv_file.print(csv_line);
       csv_file.close();
@@ -145,7 +145,7 @@ namespace csv_writer {
       } else {
         Serial.print(F("CSV - Wrote : "));
         Serial.print(csv_line);
-        last_successful_write = ntp::getLocalTime();
+        ntp::getLocalTime(last_successful_write);
       }
       updateFsInfo();
       delay(50);
@@ -156,7 +156,7 @@ namespace csv_writer {
     led_effects::onBoardLEDOff();
   }
 
-  void logIfTimeHasCome(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
+  void logIfTimeHasCome(const char *timeStamp, const int16_t &co2, const float &temperature, const float &humidity) {
     unsigned long now = seconds();
     if (now - last_written_at > config::csv_interval) {
       last_written_at = now;
diff --git a/ampel-firmware/csv_writer.h b/ampel-firmware/csv_writer.h
index 080d5cdcc2e4b2e5aa17617118120f5c5213dac6..ab4a87b2972e8b3ae597e637a6f309da0d829658 100644
--- a/ampel-firmware/csv_writer.h
+++ b/ampel-firmware/csv_writer.h
@@ -20,9 +20,9 @@ namespace config {
   extern uint16_t csv_interval; // [s]
 }
 namespace csv_writer {
-  extern String last_successful_write;
+  extern char last_successful_write[23];
   void initialize();
-  void logIfTimeHasCome(const String &timeStamp, const int16_t &co2, const float &temperature, const float &humidity);
+  void logIfTimeHasCome(const char* timestamp, const int16_t &co2, const float &temperature, const float &humidity);
   int getAvailableSpace();
   extern const String filename;
 
diff --git a/ampel-firmware/lorawan.cpp b/ampel-firmware/lorawan.cpp
index 70a02e1c8325a21a42f63402956d497264baf3d8..57fa7441e3f21e836a4a75721e47be14b63dbc85 100644
--- a/ampel-firmware/lorawan.cpp
+++ b/ampel-firmware/lorawan.cpp
@@ -33,7 +33,7 @@ void os_getDevKey(u1_t *buf) {
 namespace lorawan {
   bool waiting_for_confirmation = false;
   bool connected = false;
-  String last_transmission = "";
+  char last_transmission[23] = "";
 
   void initialize() {
     Serial.println(F("Starting LoRaWAN. Frequency plan : " LMIC_FREQUENCY_PLAN " MHz."));
@@ -65,8 +65,10 @@ namespace lorawan {
   }
 
   void onEvent(ev_t ev) {
+    char current_time[23];
+    ntp::getLocalTime(current_time);
     Serial.print("LoRa - ");
-    Serial.print(ntp::getLocalTime());
+    Serial.print(current_time);
     Serial.print(" - ");
     switch (ev) {
     case EV_JOINING:
@@ -113,7 +115,7 @@ namespace lorawan {
       Serial.println(F("EV_REJOIN_FAILED"));
       break;
     case EV_TXCOMPLETE:
-      last_transmission = ntp::getLocalTime();
+      ntp::getLocalTime(last_transmission);
       Serial.println(F("EV_TXCOMPLETE"));
       break;
     case EV_TXSTART:
diff --git a/ampel-firmware/lorawan.h b/ampel-firmware/lorawan.h
index 6cf1226f72f7385e075ff387c160d0dbdefa2ffd..45f462b2ef761066797ccd2ff114762088b5c628 100644
--- a/ampel-firmware/lorawan.h
+++ b/ampel-firmware/lorawan.h
@@ -39,7 +39,7 @@ namespace config {
 namespace lorawan {
   extern bool waiting_for_confirmation;
   extern bool connected;
-  extern String last_transmission;
+  extern char last_transmission[];
   void initialize();
   void process();
   void preparePayloadIfTimeHasCome(const int16_t &co2, const float &temp, const float &hum);
diff --git a/ampel-firmware/mqtt.cpp b/ampel-firmware/mqtt.cpp
index 516090744a5ac7c8cfed9cfdee02391b5bb78d4e..1037aa5c64a1701bbda39e984ee8ed0904f5cf27 100644
--- a/ampel-firmware/mqtt.cpp
+++ b/ampel-firmware/mqtt.cpp
@@ -25,7 +25,7 @@ namespace mqtt {
 
   String publish_topic;
   const char *json_sensor_format;
-  String last_successful_publish = "";
+  char last_successful_publish[23] = "";
 
   void initialize(String &topic) {
     json_sensor_format = PSTR("{\"time\":\"%s\", \"co2\":%d, \"temp\":%.1f, \"rh\":%.1f}");
@@ -41,17 +41,17 @@ namespace mqtt {
         " (Sends local IP and SSID via MQTT. Can be useful to find sensor)");
   }
 
-  void publish(const String &timestamp, int16_t co2, float temperature, float humidity) {
+  void publish(const char *timestamp, int16_t co2, float temperature, float humidity) {
     if (WiFi.status() == WL_CONNECTED && mqttClient.connected()) {
       led_effects::onBoardLEDOn();
       Serial.print(F("MQTT - Publishing message ... "));
 
       char payload[75]; // Should be enough for json...
-      snprintf(payload, sizeof(payload), json_sensor_format, timestamp.c_str(), co2, temperature, humidity);
+      snprintf(payload, sizeof(payload), json_sensor_format, timestamp, co2, temperature, humidity);
       // Topic is the same as clientID. e.g. 'CO2sensors/ESP3d03da'
       if (mqttClient.publish(publish_topic.c_str(), payload)) {
         Serial.println(F("OK"));
-        last_successful_publish = ntp::getLocalTime();
+        ntp::getLocalTime(last_successful_publish);
       } else {
         Serial.println(F("Failed."));
       }
@@ -120,12 +120,12 @@ namespace mqtt {
     }
   }
 
-  void publishIfTimeHasCome(const String &timeStamp, const int16_t &co2, const float &temp, const float &hum) {
+  void publishIfTimeHasCome(const char *timestamp, const int16_t &co2, const float &temp, const float &hum) {
     // Send message via MQTT according to sending interval
     unsigned long now = seconds();
     if (now - last_sent_at > config::mqtt_sending_interval) {
       last_sent_at = now;
-      publish(timeStamp, co2, temp, hum);
+      publish(timestamp, co2, temp, hum);
     }
   }
 
diff --git a/ampel-firmware/mqtt.h b/ampel-firmware/mqtt.h
index aaaa95621d10cdf0a8608700654a89b360563989..9167c47dda720528f138ff048630d399e6656984 100644
--- a/ampel-firmware/mqtt.h
+++ b/ampel-firmware/mqtt.h
@@ -11,11 +11,11 @@ namespace config {
   extern uint16_t mqtt_sending_interval; // [s]
 }
 namespace mqtt {
-  extern String last_successful_publish;
+  extern char last_successful_publish[];
   extern bool connected;
   void initialize(String &topic);
   void keepConnection();
-  void publishIfTimeHasCome(const String &timeStamp, const int16_t &co2, const float &temp, const float &hum);
+  void publishIfTimeHasCome(const char *timestamp, const int16_t &co2, const float &temp, const float &hum);
 
   void setMQTTinterval(int32_t sending_interval);
   void sendInfoAboutLocalNetwork();
diff --git a/ampel-firmware/src/lib/NTPClient-master/NTPClient.cpp b/ampel-firmware/src/lib/NTPClient-master/NTPClient.cpp
index 048a82a4bcec1d3885070fbb83db764f60369080..1b52de5af6eefae690044fa9138222fb3aa78d1b 100644
--- a/ampel-firmware/src/lib/NTPClient-master/NTPClient.cpp
+++ b/ampel-firmware/src/lib/NTPClient-master/NTPClient.cpp
@@ -152,19 +152,17 @@ int NTPClient::getSeconds() {
   return (this->getEpochTime() % 60);
 }
 
-String NTPClient::getFormattedTime(unsigned long secs) {
+void NTPClient::getFormattedTime(char *formatted_time, unsigned long secs) {
   unsigned long rawTime = secs ? secs : this->getEpochTime();
   unsigned int hours = (rawTime % 86400L) / 3600;
   unsigned int minutes = (rawTime % 3600) / 60;
   unsigned int seconds = rawTime % 60;
 
-  char formatted_time[9];
-  snprintf(formatted_time, sizeof(formatted_time), "%02d:%02d:%02d", hours, minutes, seconds);
-  return String(formatted_time);
+  snprintf(formatted_time, 9, "%02d:%02d:%02d", hours, minutes, seconds);
 }
 
 // Based on https://github.com/PaulStoffregen/Time/blob/master/Time.cpp
-String NTPClient::getFormattedDate(unsigned long secs) {
+void NTPClient::getFormattedDate(char *formatted_date, unsigned long secs) {
   unsigned long rawTime = (secs ? secs : this->getEpochTime()) / 86400L;  // in days
   unsigned long days = 0, year = 1970;
   uint8_t month;
@@ -187,11 +185,9 @@ String NTPClient::getFormattedDate(unsigned long secs) {
   month++; // jan is month 1
   rawTime++; // first day is day 1
 
-  char formatted_date[23];
-  snprintf(formatted_date, sizeof(formatted_date), "%4lu-%02d-%02lu %s%+03d",
-      year, month, rawTime, this->getFormattedTime(secs).c_str(), this->_timeOffset / 3600);
-
-  return String(formatted_date);
+  char formatted_time[9];
+  this->getFormattedTime(formatted_time, secs);
+  snprintf(formatted_date, 23, "%4lu-%02d-%02lu %s%+03d", year, month, rawTime, formatted_time, this->_timeOffset / 3600);
 }
 
 void NTPClient::end() {
diff --git a/ampel-firmware/src/lib/NTPClient-master/NTPClient.h b/ampel-firmware/src/lib/NTPClient-master/NTPClient.h
index ad450706490679ee8a459c5471efec167e419d21..3349dbb7df998fc931874c3f1ec86cda07fc3f80 100644
--- a/ampel-firmware/src/lib/NTPClient-master/NTPClient.h
+++ b/ampel-firmware/src/lib/NTPClient-master/NTPClient.h
@@ -80,7 +80,7 @@ class NTPClient {
     /**
     * @return secs argument (or 0 for current time) formatted like `hh:mm:ss`
     */
-    String getFormattedTime(unsigned long secs = 0);
+    void getFormattedTime(char *formatted_time, unsigned long secs = 0);
 
     /**
      * @return time in seconds since Jan. 1, 1970
@@ -91,7 +91,7 @@ class NTPClient {
     * @return secs argument (or 0 for current date) formatted to ISO 8601
     * like `2004-02-12T15:19:21+00:00`
     */
-    String getFormattedDate(unsigned long secs = 0);
+    void getFormattedDate(char *formatted_date, unsigned long secs = 0);
 
     /**
      * Stops the underlying UDP client
diff --git a/ampel-firmware/util.cpp b/ampel-firmware/util.cpp
index 31df19dd856e5c3f17b5eb929979660eb27db715..b548810958e8eda32ecd2beaf1c0dbbd54a88b61 100644
--- a/ampel-firmware/util.cpp
+++ b/ampel-firmware/util.cpp
@@ -33,8 +33,8 @@ namespace ntp {
     timeClient.update();
   }
 
-  String getLocalTime() {
-    return timeClient.getFormattedDate();
+  void getLocalTime(char *timestamp) {
+    timeClient.getFormattedDate(timestamp);
   }
 }
 
diff --git a/ampel-firmware/util.h b/ampel-firmware/util.h
index 2997933480b06db67b18a09bafa2d156d8b7e7b5..40f87ca0d7e05fcc738c3cc18f44a0da1cfdd748 100644
--- a/ampel-firmware/util.h
+++ b/ampel-firmware/util.h
@@ -21,7 +21,7 @@
 namespace ntp {
   void initialize();
   void update();
-  String getLocalTime();
+  void getLocalTime(char* timestamp);
 }
 
 namespace util {
diff --git a/ampel-firmware/web_server.cpp b/ampel-firmware/web_server.cpp
index c9dfeab5e2546703dc2968f5eefa45799d86282a..a9572fd347800aa4f2e59ce6ab7577f029b5e708 100644
--- a/ampel-firmware/web_server.cpp
+++ b/ampel-firmware/web_server.cpp
@@ -226,15 +226,15 @@ namespace web_server {
 
     // Body
     snprintf_P(content, sizeof(content), body_template, SENSOR_ID.c_str(), sensor::co2, sensor::temperature,
-        sensor::humidity, sensor::timestamp.c_str(), config::measurement_timestep,
+        sensor::humidity, sensor::timestamp, config::measurement_timestep,
 #ifdef AMPEL_CSV
-        csv_writer::last_successful_write.c_str(), config::csv_interval, csv_writer::getAvailableSpace() / 1024,
+        csv_writer::last_successful_write, config::csv_interval, csv_writer::getAvailableSpace() / 1024,
 #endif
 #ifdef AMPEL_MQTT
-        mqtt::connected ? "Yes" : "No", mqtt::last_successful_publish.c_str(), config::mqtt_sending_interval,
+        mqtt::connected ? "Yes" : "No", mqtt::last_successful_publish, config::mqtt_sending_interval,
 #endif
 #if defined(AMPEL_LORAWAN) && defined(ESP32)
-        lorawan::connected ? "Yes" : "No", LMIC_FREQUENCY_PLAN, lorawan::last_transmission.c_str(),
+        lorawan::connected ? "Yes" : "No", LMIC_FREQUENCY_PLAN, lorawan::last_transmission,
         config::lorawan_sending_interval,
 #endif
         config::temperature_offset, config::auto_calibrate_sensor ? "Yes" : "No", SENSOR_ID.c_str(), SENSOR_ID.c_str(),