summaryrefslogtreecommitdiff
path: root/src/main/cpp/timezone.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/cpp/timezone.cpp')
-rw-r--r--src/main/cpp/timezone.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/main/cpp/timezone.cpp b/src/main/cpp/timezone.cpp
new file mode 100644
index 0000000..a14aebd
--- /dev/null
+++ b/src/main/cpp/timezone.cpp
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#if defined(_MSC_VER)
+#pragma warning ( disable: 4231 4251 4275 4786 )
+#endif
+
+
+#define __STDC_CONSTANT_MACROS
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/timezone.h>
+#include <stdlib.h>
+
+#include <apr_time.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/pool.h>
+#include <log4cxx/logger.h>
+
+using namespace log4cxx;
+using namespace log4cxx::helpers;
+
+IMPLEMENT_LOG4CXX_OBJECT( TimeZone )
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ namespace TimeZoneImpl
+ {
+ /** Time zone object that represents GMT. */
+ class GMTTimeZone : public TimeZone
+ {
+ public:
+ /** Class factory. */
+ static const TimeZonePtr & getInstance()
+ {
+ static TimeZonePtr tz( new GMTTimeZone() );
+ return tz;
+ }
+
+ /** Explode time to human readable form. */
+ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const
+ {
+ apr_status_t stat;
+ // APR 1.1 and early mishandles microseconds on dates
+ // before 1970, APR bug 32520
+ if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) {
+ apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC;
+ stat = apr_time_exp_gmt(result, floorTime);
+ result->tm_usec = (int) (input - floorTime);
+ } else {
+ stat = apr_time_exp_gmt( result, input );
+ }
+ return stat;
+ }
+
+ private:
+ GMTTimeZone() : TimeZone( LOG4CXX_STR("GMT") )
+ {
+ }
+ };
+
+
+
+ /** Time zone object that represents GMT. */
+ class LocalTimeZone : public TimeZone
+ {
+ public:
+ /** Class factory. */
+ static const TimeZonePtr & getInstance()
+ {
+ static TimeZonePtr tz( new LocalTimeZone() );
+ return tz;
+ }
+
+ /** Explode time to human readable form. */
+ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const
+ {
+ apr_status_t stat;
+ // APR 1.1 and early mishandles microseconds on dates
+ // before 1970, APR bug 32520
+ if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) {
+ apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC;
+ stat = apr_time_exp_lt(result, floorTime);
+ result->tm_usec = (int) (input - floorTime);
+ } else {
+ stat = apr_time_exp_lt( result, input );
+ }
+ return stat;
+ }
+
+
+ private:
+ LocalTimeZone() : TimeZone( getTimeZoneName() )
+ {
+ }
+
+ static const LogString getTimeZoneName()
+ {
+ const int MAX_TZ_LENGTH = 255;
+ char tzName[MAX_TZ_LENGTH];
+ apr_size_t tzLength;
+ apr_time_exp_t tm;
+ apr_time_exp_lt(&tm, 0);
+ apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%Z", &tm);
+ if (tzLength == 0) {
+ apr_strftime(tzName, &tzLength, MAX_TZ_LENGTH, "%z", &tm);
+ }
+ tzName[tzLength] = 0;
+ LogString retval;
+ log4cxx::helpers::Transcoder::decode(tzName, retval);
+ return retval;
+ }
+
+ };
+
+
+
+ /** Time zone object that represents a fixed offset from GMT. */
+ class FixedTimeZone : public TimeZone
+ {
+ public:
+ FixedTimeZone( const LogString & name, apr_int32_t offset1 ) : TimeZone( name ), offset( offset1 )
+ {
+ }
+
+ /** Explode time to human readable form. */
+ log4cxx_status_t explode( apr_time_exp_t * result, log4cxx_time_t input ) const
+ {
+ apr_status_t stat;
+ // APR 1.1 and early mishandles microseconds on dates
+ // before 1970, APR bug 32520
+ if (LOG4CXX_UNLIKELY(input < 0 && apr_time_usec(input) < 0)) {
+ apr_time_t floorTime = (apr_time_sec(input) -1) * APR_USEC_PER_SEC;
+ stat = apr_time_exp_tz(result, floorTime, offset);
+ result->tm_usec = (int) (input - floorTime);
+ } else {
+ stat = apr_time_exp_tz( result, input, offset );
+ }
+ return stat;
+ }
+
+
+ private:
+ const apr_int32_t offset;
+ };
+
+ }
+ }
+}
+
+
+
+TimeZone::TimeZone( const LogString & id1 ) : id( id1 )
+{
+}
+
+TimeZone::~TimeZone()
+{
+}
+
+const TimeZonePtr & TimeZone::getDefault()
+{
+ return log4cxx::helpers::TimeZoneImpl::LocalTimeZone::getInstance();
+}
+
+const TimeZonePtr & TimeZone::getGMT()
+{
+ return log4cxx::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
+}
+
+const TimeZonePtr TimeZone::getTimeZone( const LogString & id )
+{
+ const logchar gmt[] = { 0x47, 0x4D, 0x54, 0 };
+ if ( id == gmt )
+ {
+ return log4cxx::helpers::TimeZoneImpl::GMTTimeZone::getInstance();
+ }
+ if ( id.length() >= 5 && id.substr( 0, 3 ) == gmt )
+ {
+ int hours = 0;
+ int minutes = 0;
+ int sign = 1;
+ if (id[3] == 0x2D /* '-' */) {
+ sign = -1;
+ }
+ LogString off( id.substr( 4 ) );
+ if ( id.length() >= 7 )
+ {
+ size_t colonPos = off.find( 0x3A /* ':' */);
+ if ( colonPos == LogString::npos )
+ {
+ minutes = StringHelper::toInt(off.substr(off.length() - 2));
+ hours = StringHelper::toInt(off.substr(0, off.length() - 2));
+ }
+ else
+ {
+ minutes = StringHelper::toInt(off.substr(colonPos + 1));
+ hours = StringHelper::toInt(off.substr(0, colonPos));
+ }
+ } else {
+ hours = StringHelper::toInt(off);
+ }
+ LogString s(gmt);
+ Pool p;
+ LogString hh;
+ StringHelper::toString(hours, p, hh);
+ if (sign > 0) {
+ s.append(1, (logchar) 0x2B /* '+' */);
+ } else {
+ s.append(1, (logchar) 0x2D /* '-' */);
+ }
+ if (hh.length() == 1) {
+ s.append(1, (logchar) 0x30 /* '0' */);
+ }
+ s.append(hh);
+ s.append(1, (logchar) 0x3A /*' :' */);
+ LogString mm;
+ StringHelper::toString(minutes, p, mm);
+ if (mm.length() == 1) {
+ s.append(1, (logchar) 0x30 /* '0' */);
+ }
+ s.append(mm);
+ apr_int32_t offset = sign * (hours * 3600 + minutes * 60);
+ return new log4cxx::helpers::TimeZoneImpl::FixedTimeZone( s, offset );
+ }
+ const TimeZonePtr & ltz = getDefault();
+ if ( ltz->getID() == id )
+ {
+ return ltz;
+ }
+ return getGMT();
+}
+