Index: trunk/lib/App.inc.php
===================================================================
--- trunk/lib/App.inc.php	(revision 659)
+++ trunk/lib/App.inc.php	(revision 660)
@@ -119,4 +119,9 @@
         'sql_time_format' => '%k:%i',
 
+        // Timezone support. No codebase apps currently support switching timezones, but we explicitly set these so they're consistent.
+        'user_timezone' => 'UTC',
+        'php_timezone' => 'UTC',
+        'mysql_timezone' => 'UTC',
+
         // Use php sessions?
         'enable_session' => false,
@@ -370,33 +375,7 @@
         }
 
-        // If the 'timezone' parameter is not set, check for a tz cookie.
-        if (!$this->getParam('timezone') && isset($_COOKIE['tz']) && '' != $_COOKIE['tz']) {
-            if (preg_match('!^[A-Z_/-]{3,}$!i', $_COOKIE['tz'])) {
-                // Valid: tz cookie has a timezone name, like "UTC" or "America/Mexico_City".
-                $this->setParam(array('timezone' => $_COOKIE['tz']));
-            } else if (is_numeric($_COOKIE['tz']) && $_COOKIE['tz'] > -12 && $_COOKIE['tz'] < 14) { // https://en.wikipedia.org/wiki/List_of_UTC_time_offsets#UTC+14:00,_M%E2%80%A0
-                // tz cookie has a timezone offset, like "-6" (assume UTC).
-                $tz = timezone_name_from_abbr('', $_COOKIE['tz'] * 3600, 0);
-                if ($tz && preg_match('!^[A-Z_/-]{3,}$!i', $tz)) {
-                    // Valid.
-                    $this->setParam(array('timezone' => $tz));
-                } else {
-                    $this->logMsg(sprintf('Failed to convert UTC offset to timezone: %s', $_COOKIE['tz']), LOG_NOTICE, __FILE__, __LINE__);
-                }
-            } else {
-                $this->logMsg(sprintf('Invalid timezone cookie value: %s', $_COOKIE['tz']), LOG_NOTICE, __FILE__, __LINE__);
-            }
-        }
-        if ($this->getParam('timezone')) {
-            // Set timezone of the user.
-            if (date_default_timezone_set($this->getParam('timezone'))) {
-                $this->logMsg(sprintf('Using timezone: %s', $this->getParam('timezone')), LOG_DEBUG, __FILE__, __LINE__);
-            } else {
-                // Failed: unset the timezone parameter so it isn't used to set the database timezone.
-                $this->setParam(array('timezone' => null));
-                $this->logMsg(sprintf('Failed to set timezone: %s', $this->getParam('timezone')), LOG_NOTICE, __FILE__, __LINE__);
-            }
-        } else {
-            $this->logMsg(sprintf('Using server timezone: %s', date_default_timezone_get()), LOG_DEBUG, __FILE__, __LINE__);
+        // Server timezone used internally by PHP.
+        if ($this->getParam('php_timezone')) {
+            $this->setTimezone($this->getParam('php_timezone'));
         }
 
@@ -446,4 +425,5 @@
                 'db_debug' => $this->getParam('db_debug'),
                 'db_die_on_failure' => $this->getParam('db_die_on_failure'),
+                'timezone' => $this->getParam('mysql_timezone'),
             ));
 
@@ -1706,3 +1686,24 @@
         return $ret;
     }
+
+    /*
+    * Set timezone used internally by PHP.
+    *
+    * @access   public
+    * @param    string  $tz     Timezone, e.g., America/Mexico_City
+    * @return
+    * @author   Quinn Comendant <quinn@strangecode.com>
+    * @since    28 Jan 2019 16:38:38
+    */
+    public function setTimezone($tz)
+    {
+        $this->setTimezone();
+        // Set timezone for PHP.
+        if (date_default_timezone_set($tz)) {
+            $this->logMsg(sprintf('Using php timezone: %s', $tz), LOG_DEBUG, __FILE__, __LINE__);
+        } else {
+            // Failed!
+            $this->logMsg(sprintf('Failed to set php timezone: %s', $tz), LOG_WARNING, __FILE__, __LINE__);
+        }
+    }
 } // End.
Index: trunk/lib/DB.inc.php
===================================================================
--- trunk/lib/DB.inc.php	(revision 659)
+++ trunk/lib/DB.inc.php	(revision 660)
@@ -69,4 +69,7 @@
         'zero_date' => '0000-00-00',
         'infinity_date' => '9999-12-31',
+
+        // Timezone for MySQL.
+        'timezone' => 'UTC',
     );
 
@@ -189,7 +192,9 @@
         $this->_connected = true;
 
+        $init_sql = array();
+
         // Tell MySQL what character set we're using. Available only on MySQL versions > 4.01.01.
         if ('' != $app->getParam('character_set') && isset($this->mysql_character_sets[mb_strtolower($app->getParam('character_set'))])) {
-            $this->query("/*!40101 SET NAMES '" . $this->mysql_character_sets[mb_strtolower($app->getParam('character_set'))] . "' */");
+            $init_sql[] = sprintf("SET NAMES '%s'", $this->mysql_character_sets[mb_strtolower($app->getParam('character_set'))]);
         } else {
             $app->logMsg(sprintf('%s is not a known character_set.', $app->getParam('character_set')), LOG_ERR, __FILE__, __LINE__);
@@ -201,10 +206,13 @@
         }
 
-        // Set timezone.
-        $tz = date_default_timezone_get();
-        // Check that PHP is configured with a valid timezone name, e.g., "UTC" or "America/Mexico_City" or "-6:00".
-        if ($app->getParam('timezone') && $app->getParam('timezone') == $tz && preg_match('!^([A-Z_/-]{3,}|[-+\d:]+)$!i', $tz)) {
+        // Set MySQL session timezone.
+        if ($this->getParam('timezone')) {
             // https://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html
-            $this->query(sprintf("SET SESSION time_zone = '%s'", $tz));
+            $init_sql[] = sprintf("SET time_zone = '%s'", $this->getParam('timezone'));
+        }
+
+        // Run init query, if set.
+        if (!empty($init_sql)) {
+            $this->query(join('; ', $init_sql));
         }
 
@@ -506,5 +514,4 @@
     }
 
-
 } // End.
 
