mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 21:23:04 +01:00
Slightly adjust Dmitry's Firebird::TimeStamp class to make it more useful, change is coordiated with Dmitry. Use thread-safe localtime_r routine when it is available
This commit is contained in:
parent
498990bf55
commit
933063c7ce
@ -177,6 +177,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\common\classes\timestamp.cpp">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\common\utils.cpp">
|
RelativePath="..\..\..\src\common\utils.cpp">
|
||||||
</File>
|
</File>
|
||||||
@ -211,6 +214,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\jrd\os\fbsyslog.h">
|
RelativePath="..\..\..\src\jrd\os\fbsyslog.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\common\classes\timestamp.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\common\utils_proto.h">
|
RelativePath="..\..\..\src\common\utils_proto.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -177,6 +177,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\common\classes\timestamp.cpp">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\common\utils.cpp">
|
RelativePath="..\..\..\src\common\utils.cpp">
|
||||||
</File>
|
</File>
|
||||||
@ -208,6 +211,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\common\config\dir_list.h">
|
RelativePath="..\..\..\src\common\config\dir_list.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\common\classes\timestamp.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\common\utils_proto.h">
|
RelativePath="..\..\..\src\common\utils_proto.h">
|
||||||
</File>
|
</File>
|
||||||
|
@ -173,6 +173,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
RelativePath="..\..\..\src\jrd\os\win32\path_utils.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\common\classes\timestamp.cpp">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\common\utils.cpp">
|
RelativePath="..\..\..\src\common\utils.cpp">
|
||||||
</File>
|
</File>
|
||||||
@ -207,6 +210,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath="..\..\..\src\jrd\os\fbsyslog.h">
|
RelativePath="..\..\..\src\jrd\os\fbsyslog.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\..\src\common\classes\timestamp.h">
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
<Globals>
|
<Globals>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
dnl $Id: configure.in,v 1.208 2004-10-25 09:45:03 aafemt Exp $
|
dnl $Id: configure.in,v 1.209 2004-11-04 19:14:08 skidder Exp $
|
||||||
|
|
||||||
dnl ############################# INITIALISATION ###############################
|
dnl ############################# INITIALISATION ###############################
|
||||||
|
|
||||||
@ -457,6 +457,7 @@ AC_CHECK_FUNCS(tcgetattr strdup)
|
|||||||
AC_CHECK_FUNCS(mkstemp)
|
AC_CHECK_FUNCS(mkstemp)
|
||||||
AC_CHECK_FUNCS(pthread_keycreate pthread_key_create)
|
AC_CHECK_FUNCS(pthread_keycreate pthread_key_create)
|
||||||
AC_CHECK_FUNCS(llrint)
|
AC_CHECK_FUNCS(llrint)
|
||||||
|
AC_CHECK_FUNCS(localtime_r)
|
||||||
|
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
@ -3,25 +3,25 @@
|
|||||||
* MODULE: timestamp.cpp
|
* MODULE: timestamp.cpp
|
||||||
* DESCRIPTION: Date/time handling class
|
* DESCRIPTION: Date/time handling class
|
||||||
*
|
*
|
||||||
* The contents of this file are subject to the Initial
|
* The contents of this file are subject to the Interbase Public
|
||||||
* Developer's Public License Version 1.0 (the "License");
|
* License Version 1.0 (the "License"); you may not use this file
|
||||||
* you may not use this file except in compliance with the
|
* except in compliance with the License. You may obtain a copy
|
||||||
* License. You may obtain a copy of the License at
|
* of the License at http://www.Inprise.com/IPL.html
|
||||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
|
||||||
*
|
*
|
||||||
* Software distributed under the License is distributed AS IS,
|
* Software distributed under the License is distributed on an
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||||
* See the License for the specific language governing rights
|
* or implied. See the License for the specific language governing
|
||||||
* and limitations under the License.
|
* rights and limitations under the License.
|
||||||
*
|
*
|
||||||
* The Original Code was created by Dmitry Yemanov
|
* The Original Code was created by Inprise Corporation
|
||||||
* for the Firebird Open Source RDBMS project.
|
* and its predecessors. Portions created by Inprise Corporation are
|
||||||
*
|
* Copyright (C) Inprise Corporation.
|
||||||
* Copyright (c) 2004 Dmitry Yemanov <dimitr@users.sourceforge.net>
|
|
||||||
* and all contributors signed below.
|
|
||||||
*
|
*
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* Contributor(s): ______________________________________.
|
* Contributor(s): ______________________________________.
|
||||||
|
*
|
||||||
|
* NS: The code now contains much of the logic from original gds.c
|
||||||
|
* this is why we need to use IPL license for it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "firebird.h"
|
#include "firebird.h"
|
||||||
@ -29,17 +29,6 @@
|
|||||||
#include "../jrd/dsc.h"
|
#include "../jrd/dsc.h"
|
||||||
#include "../jrd/gdsassert.h"
|
#include "../jrd/gdsassert.h"
|
||||||
|
|
||||||
#if defined(TIME_WITH_SYS_TIME)
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
|
||||||
#else
|
|
||||||
#if defined(HAVE_SYS_TIME_H)
|
|
||||||
#include <sys/time.h>
|
|
||||||
#else
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_TIMES_H
|
#ifdef HAVE_SYS_TIMES_H
|
||||||
#include <sys/times.h>
|
#include <sys/times.h>
|
||||||
#endif
|
#endif
|
||||||
@ -51,95 +40,205 @@
|
|||||||
|
|
||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
|
|
||||||
TimeStamp::TimeStamp(bool empty)
|
int TimeStamp::yday(const struct tm* times)
|
||||||
{
|
{
|
||||||
if (empty)
|
/**************************************
|
||||||
{
|
*
|
||||||
invalidate();
|
* y d a y
|
||||||
}
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* Convert a calendar date to the day-of-year.
|
||||||
|
*
|
||||||
|
* The unix time structure considers
|
||||||
|
* january 1 to be Year day 0, although it
|
||||||
|
* is day 1 of the month. (Note that QLI,
|
||||||
|
* when printing Year days takes the other
|
||||||
|
* view.)
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
SSHORT day = times->tm_mday;
|
||||||
|
const SSHORT month = times->tm_mon;
|
||||||
|
const SSHORT year = times->tm_year + 1900;
|
||||||
|
|
||||||
|
--day;
|
||||||
|
|
||||||
|
day += (214 * month + 3) / 7;
|
||||||
|
|
||||||
|
if (month < 2)
|
||||||
|
return day;
|
||||||
|
|
||||||
|
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
|
||||||
|
--day;
|
||||||
else
|
else
|
||||||
{
|
day -= 2;
|
||||||
generate();
|
|
||||||
}
|
return day;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeStamp::invalidate()
|
|
||||||
{
|
|
||||||
seconds = fractions = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimeStamp::validate()
|
void TimeStamp::decode_date(ISC_DATE nday, struct tm* times)
|
||||||
{
|
{
|
||||||
if (!seconds)
|
/**************************************
|
||||||
{
|
*
|
||||||
generate();
|
* d e c o d e _ d a t e
|
||||||
}
|
*
|
||||||
}
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* Convert a numeric day to [day, month, year].
|
||||||
|
*
|
||||||
|
* Calenders are divided into 4 year cycles.
|
||||||
|
* 3 Non-Leap years, and 1 leap year.
|
||||||
|
* Each cycle takes 365*4 + 1 == 1461 days.
|
||||||
|
* There is a further cycle of 100 4 year cycles.
|
||||||
|
* Every 100 years, the normally expected leap year
|
||||||
|
* is not present. Every 400 years it is.
|
||||||
|
* This cycle takes 100 * 1461 - 3 == 146097 days
|
||||||
|
* The origin of the constant 2400001 is unknown.
|
||||||
|
* The origin of the constant 1721119 is unknown.
|
||||||
|
* The difference between 2400001 and 1721119 is the
|
||||||
|
* number of days From 0/0/0000 to our base date of
|
||||||
|
* 11/xx/1858. (678882)
|
||||||
|
* The origin of the constant 153 is unknown.
|
||||||
|
*
|
||||||
|
* This whole routine has problems with ndates
|
||||||
|
* less than -678882 (Approx 2/1/0000).
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
// struct tm may include arbitrary number of additional members.
|
||||||
|
// zero-initialize them.
|
||||||
|
memset(times, 0, sizeof(struct tm));
|
||||||
|
|
||||||
bool TimeStamp::encode(tm* times) const
|
nday -= 1721119 - 2400001;
|
||||||
{
|
const SLONG century = (4 * nday - 1) / 146097;
|
||||||
fb_assert(seconds > 0);
|
nday = 4 * nday - 1 - 146097 * century;
|
||||||
const tm* t = localtime(&seconds);
|
SLONG day = nday / 4;
|
||||||
if (!t)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*times = *t;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimeStamp::encode(ISC_TIMESTAMP* ts, bool precise) const
|
nday = (4 * day + 3) / 1461;
|
||||||
{
|
day = 4 * day + 3 - 1461 * nday;
|
||||||
tm times;
|
day = (day + 4) / 4;
|
||||||
if (!encode(×))
|
|
||||||
{
|
SLONG month = (5 * day - 3) / 153;
|
||||||
return false;
|
day = 5 * day - 3 - 153 * month;
|
||||||
|
day = (day + 5) / 5;
|
||||||
|
|
||||||
|
SLONG year = 100 * century + nday;
|
||||||
|
|
||||||
|
if (month < 10)
|
||||||
|
month += 3;
|
||||||
|
else {
|
||||||
|
month -= 9;
|
||||||
|
year += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int day = times.tm_mday;
|
times->tm_mday = (int) day;
|
||||||
int month = times.tm_mon + 1;
|
times->tm_mon = (int) month - 1;
|
||||||
int year = times.tm_year + 1900;
|
times->tm_year = (int) year - 1900;
|
||||||
|
|
||||||
|
times->tm_yday = yday(times);
|
||||||
|
|
||||||
|
if ((times->tm_wday = (nday + 3) % 7) < 0)
|
||||||
|
times->tm_wday += 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ISC_DATE TimeStamp::encode_date(const struct tm* times)
|
||||||
|
{
|
||||||
|
/**************************************
|
||||||
|
*
|
||||||
|
* e n c o d e _ d a t e
|
||||||
|
*
|
||||||
|
**************************************
|
||||||
|
*
|
||||||
|
* Functional description
|
||||||
|
* Convert a calendar date to a numeric day
|
||||||
|
* (the number of days since the base date).
|
||||||
|
*
|
||||||
|
**************************************/
|
||||||
|
const SSHORT day = times->tm_mday;
|
||||||
|
SSHORT month = times->tm_mon + 1;
|
||||||
|
SSHORT year = times->tm_year + 1900;
|
||||||
|
|
||||||
if (month > 2)
|
if (month > 2)
|
||||||
{
|
|
||||||
month -= 3;
|
month -= 3;
|
||||||
}
|
else {
|
||||||
else
|
|
||||||
{
|
|
||||||
month += 9;
|
month += 9;
|
||||||
year -= 1;
|
year -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int c = year / 100;
|
const SLONG c = year / 100;
|
||||||
const int ya = year - 100 * c;
|
const SLONG ya = year - 100 * c;
|
||||||
|
|
||||||
ts->timestamp_date =
|
return (ISC_DATE) (((SINT64) 146097 * c) / 4 +
|
||||||
(((SINT64) 146097 * c) / 4 + (1461 * ya) / 4 +
|
(1461 * ya) / 4 +
|
||||||
(153 * month + 2) / 5 + day + 1721119 - 2400001);
|
(153 * month + 2) / 5 + day + 1721119 - 2400001);
|
||||||
|
}
|
||||||
|
|
||||||
ts->timestamp_time =
|
// Encode timestamp from UNIX datetime structure
|
||||||
((times.tm_hour * 60 + times.tm_min) * 60 +
|
void TimeStamp::encode(const struct tm* times) {
|
||||||
times.tm_sec) * ISC_TIME_SECONDS_PRECISION +
|
mValue.timestamp_date = encode_date(times);
|
||||||
(precise ? fractions * 10 : 0);
|
mValue.timestamp_time =
|
||||||
|
((times->tm_hour * 60 + times->tm_min) * 60 +
|
||||||
|
times->tm_sec) * ISC_TIME_SECONDS_PRECISION;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
// Decode timestamp into UNIX datetime structure
|
||||||
|
void TimeStamp::decode(struct tm* times) const {
|
||||||
|
decode_date(mValue.timestamp_date, times);
|
||||||
|
|
||||||
|
const ULONG minutes = mValue.timestamp_time / (ISC_TIME_SECONDS_PRECISION * 60);
|
||||||
|
times->tm_hour = minutes / 60;
|
||||||
|
times->tm_min = minutes % 60;
|
||||||
|
times->tm_sec = (mValue.timestamp_time / ISC_TIME_SECONDS_PRECISION) % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimeStamp::generate()
|
void TimeStamp::generate()
|
||||||
{
|
{
|
||||||
// Only millisecond precision is supported currently
|
// NS: We round generated timestamps to whole millisecond.
|
||||||
|
// Not many applications can deal with fractional milliseconds properly and
|
||||||
|
// we do not use high resolution timers either so actual time granularity
|
||||||
|
// is going to to be somewhere in range between 1 ms (like on UNIX/Risc)
|
||||||
|
// and 53 ms (such as Win9X)
|
||||||
|
|
||||||
|
time_t seconds; // UTC time
|
||||||
|
int fractions; // milliseconds
|
||||||
|
|
||||||
#ifdef HAVE_GETTIMEOFDAY
|
#ifdef HAVE_GETTIMEOFDAY
|
||||||
struct timeval tp;
|
struct timeval tp;
|
||||||
GETTIMEOFDAY(&tp);
|
GETTIMEOFDAY(&tp);
|
||||||
seconds = tp.tv_sec;
|
seconds = tp.tv_sec;
|
||||||
fractions = tp.tv_usec / 1000;
|
millis = tp.tv_usec / 1000;
|
||||||
#else
|
#else
|
||||||
struct timeb time_buffer;
|
struct timeb time_buffer;
|
||||||
ftime(&time_buffer);
|
ftime(&time_buffer);
|
||||||
seconds = time_buffer.time;
|
seconds = time_buffer.time;
|
||||||
fractions = time_buffer.millitm;
|
fractions = time_buffer.millitm;
|
||||||
#endif
|
#endif
|
||||||
fb_assert(seconds > 0);
|
|
||||||
|
// NS: Current FB behavior of using server time zone is not appropriate for
|
||||||
|
// distributed applications. We should be storing UTC times everywhere and
|
||||||
|
// convert timestamps to client timezone as necessary. Replace localtime
|
||||||
|
// stuff with these lines as soon appropriate functionality is implemented
|
||||||
|
//
|
||||||
|
// mValue.timestamp_date = seconds / 86400 + GDS_EPOCH_START;
|
||||||
|
// mValue.timestamp_time = (seconds % 86400) * ISC_TIME_SECONDS_PRECISION;
|
||||||
|
|
||||||
|
#ifdef HAVE_LOCALTIME_R
|
||||||
|
struct tm times;
|
||||||
|
if (!localtime_r(&seconds, ×))
|
||||||
|
system_call_failed::raise("localtime_r");
|
||||||
|
encode(×);
|
||||||
|
#else
|
||||||
|
struct tm *times = localtime(&seconds);
|
||||||
|
if (!times)
|
||||||
|
system_call_failed::raise("localtime");
|
||||||
|
encode(times);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Add fractions of second
|
||||||
|
mValue.timestamp_time += fractions * ISC_TIME_SECONDS_PRECISION / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -27,25 +27,86 @@
|
|||||||
#ifndef CLASSES_TIMESTAMP_H
|
#ifndef CLASSES_TIMESTAMP_H
|
||||||
#define CLASSES_TIMESTAMP_H
|
#define CLASSES_TIMESTAMP_H
|
||||||
|
|
||||||
|
// struct tm declaration
|
||||||
|
#if defined(TIME_WITH_SYS_TIME)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
#else
|
||||||
|
#if defined(HAVE_SYS_TIME_H)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#else
|
||||||
|
#include <time.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Firebird {
|
namespace Firebird {
|
||||||
|
|
||||||
|
// Wrapper class for ISC_TIMESTAMP supposed to implement date/time conversions
|
||||||
|
// and arithmetic. Small and not platform-specific methods are implemented
|
||||||
|
// inline. Usage of this class normally should involve zero overhead.
|
||||||
|
//
|
||||||
|
// Note: default "shallow-copy" constructor and assignment operators
|
||||||
|
// are just fine for our purposes
|
||||||
|
//
|
||||||
|
// TODO: migrate fbudf to this class.
|
||||||
class TimeStamp
|
class TimeStamp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Number of the first day of UNIX epoch in GDS counting
|
||||||
|
enum { GDS_EPOCH_START = 40617 };
|
||||||
|
|
||||||
explicit TimeStamp(bool empty = false);
|
// Default constructor. Fills timestamp with current date/time
|
||||||
|
TimeStamp() { generate(); }
|
||||||
|
|
||||||
void invalidate();
|
// Altername constructor, may create empty timestamp object
|
||||||
void validate();
|
explicit TimeStamp(bool zero)
|
||||||
|
{
|
||||||
|
if (zero)
|
||||||
|
invalidate();
|
||||||
|
else
|
||||||
|
generate();
|
||||||
|
}
|
||||||
|
|
||||||
bool encode(tm* times) const;
|
// Construct wrapper around pre-existing timestamp
|
||||||
bool encode(ISC_TIMESTAMP* ts, bool precise) const;
|
TimeStamp(const ISC_TIMESTAMP& from) : mValue(from) { }
|
||||||
|
|
||||||
|
// See if timestamp contains non-zero value
|
||||||
|
bool isEmpty() const {
|
||||||
|
return mValue.timestamp_date == 0 && mValue.timestamp_time == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set value of timestamp to zero
|
||||||
|
void invalidate() {
|
||||||
|
mValue.timestamp_date = 0;
|
||||||
|
mValue.timestamp_time = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign value of timestamp to current date/time if it is zero
|
||||||
|
void validate() {
|
||||||
|
if (isEmpty()) generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode timestamp from UNIX datetime structure
|
||||||
|
void encode(const struct tm* times);
|
||||||
|
|
||||||
|
// Decode timestamp into UNIX datetime structure
|
||||||
|
void decode(struct tm* times) const;
|
||||||
|
|
||||||
|
// Write access to timestamp structure we wrap
|
||||||
|
ISC_TIMESTAMP& value() { return mValue; }
|
||||||
|
|
||||||
|
// Read access to timestamp structure we wrap
|
||||||
|
const ISC_TIMESTAMP& value() const { return mValue; }
|
||||||
|
|
||||||
|
// ISC date/time helper routines. Both functions are signal-safe.
|
||||||
|
static void decode_date(ISC_DATE nday, struct tm* times);
|
||||||
|
static ISC_DATE encode_date(const struct tm* times);
|
||||||
private:
|
private:
|
||||||
|
ISC_TIMESTAMP mValue;
|
||||||
|
|
||||||
time_t seconds;
|
static int yday(const struct tm* times);
|
||||||
time_t fractions;
|
|
||||||
|
|
||||||
|
// Assign value of timestamp to current date/time
|
||||||
void generate();
|
void generate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,6 +159,7 @@
|
|||||||
#define HAVE_STRDUP
|
#define HAVE_STRDUP
|
||||||
#undef HAVE_MKSTEMP
|
#undef HAVE_MKSTEMP
|
||||||
#undef HAVE_LLRINT
|
#undef HAVE_LLRINT
|
||||||
|
#undef HAVE_LOCALTIME_R
|
||||||
|
|
||||||
|
|
||||||
/* Types */
|
/* Types */
|
||||||
|
@ -1377,24 +1377,17 @@ void CVT_move(const dsc* from, dsc* to, FPTR_ERROR err)
|
|||||||
Otherwise, take the CURRENT date to populate the
|
Otherwise, take the CURRENT date to populate the
|
||||||
date portion of the timestamp */
|
date portion of the timestamp */
|
||||||
|
|
||||||
ISC_TIMESTAMP enc_times;
|
SLONG cur_date;
|
||||||
if (tdbb && (tdbb->getType() == ThreadData::tddDBB) &&
|
if (tdbb && (tdbb->getType() == ThreadData::tddDBB) &&
|
||||||
tdbb->tdbb_request)
|
tdbb->tdbb_request)
|
||||||
{
|
{
|
||||||
if (!tdbb->tdbb_request->req_timestamp.encode(&enc_times, false))
|
cur_date = tdbb->tdbb_request->req_timestamp.value().timestamp_date;
|
||||||
{
|
|
||||||
(*err)(isc_date_range_exceeded, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!Firebird::TimeStamp().encode(&enc_times, false))
|
cur_date = Firebird::TimeStamp().value().timestamp_date;
|
||||||
{
|
|
||||||
(*err)(isc_date_range_exceeded, 0);
|
|
||||||
}
|
}
|
||||||
}
|
((GDS_TIMESTAMP*) (to->dsc_address))->timestamp_date = cur_date;
|
||||||
((GDS_TIMESTAMP*) (to->dsc_address))->timestamp_date =
|
|
||||||
enc_times.timestamp_date;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2498,15 +2491,10 @@ static void string_to_datetime(
|
|||||||
conversion_error(desc, err);
|
conversion_error(desc, err);
|
||||||
|
|
||||||
/* fetch the current time */
|
/* fetch the current time */
|
||||||
|
*date = Firebird::TimeStamp().value();
|
||||||
|
|
||||||
if (!Firebird::TimeStamp().encode(date, true))
|
if (strcmp(temp, NOW) == 0)
|
||||||
{
|
|
||||||
(err)(isc_date_range_exceeded, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(temp, NOW) == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (expect_type == expect_sql_time) {
|
if (expect_type == expect_sql_time) {
|
||||||
conversion_error(desc, err);
|
conversion_error(desc, err);
|
||||||
return;
|
return;
|
||||||
@ -2631,10 +2619,8 @@ static void string_to_datetime(
|
|||||||
times.tm_mon = components[position_month];
|
times.tm_mon = components[position_month];
|
||||||
times.tm_mday = components[position_day];
|
times.tm_mday = components[position_day];
|
||||||
|
|
||||||
if (!Firebird::TimeStamp().encode(×2))
|
// Fetch current date/time
|
||||||
{
|
Firebird::TimeStamp().decode(×2);
|
||||||
(err)(isc_date_range_exceeded, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle defaulting of year */
|
/* Handle defaulting of year */
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
*
|
*
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
* Contributor(s): ______________________________________.
|
* Contributor(s): ______________________________________.
|
||||||
* $Id: evl.cpp,v 1.119 2004-11-01 08:29:16 dimitr Exp $
|
* $Id: evl.cpp,v 1.120 2004-11-04 19:14:20 skidder Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -943,12 +943,7 @@ dsc* EVL_expr(thread_db* tdbb, jrd_nod* node)
|
|||||||
{
|
{
|
||||||
// Use the request timestamp
|
// Use the request timestamp
|
||||||
|
|
||||||
ISC_TIMESTAMP enc_times;
|
ISC_TIMESTAMP enc_times = request->req_timestamp.value();
|
||||||
if (!request->req_timestamp.encode(&enc_times,
|
|
||||||
node->nod_type == nod_current_timestamp))
|
|
||||||
{
|
|
||||||
ERR_post(isc_date_range_exceeded, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&impure->vlu_desc, 0, sizeof(impure->vlu_desc));
|
memset(&impure->vlu_desc, 0, sizeof(impure->vlu_desc));
|
||||||
impure->vlu_desc.dsc_address =
|
impure->vlu_desc.dsc_address =
|
||||||
|
186
src/jrd/gds.cpp
186
src/jrd/gds.cpp
@ -50,6 +50,7 @@
|
|||||||
#include "../jrd/constants.h"
|
#include "../jrd/constants.h"
|
||||||
|
|
||||||
#include "../common/classes/locks.h"
|
#include "../common/classes/locks.h"
|
||||||
|
#include "../common/classes/timestamp.h"
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -193,6 +194,7 @@ static char ib_prefix_msg_val[MAXPATHLEN];
|
|||||||
#include "../jrd/jrd.h"
|
#include "../jrd/jrd.h"
|
||||||
#include "../common/utils_proto.h"
|
#include "../common/utils_proto.h"
|
||||||
|
|
||||||
|
using Firebird::TimeStamp;
|
||||||
|
|
||||||
// This structure is used to parse the firebird.msg file.
|
// This structure is used to parse the firebird.msg file.
|
||||||
struct gds_msg
|
struct gds_msg
|
||||||
@ -241,10 +243,6 @@ static void blr_print_verb(gds_ctl*, SSHORT);
|
|||||||
static int blr_print_word(gds_ctl*);
|
static int blr_print_word(gds_ctl*);
|
||||||
|
|
||||||
static void init(void);
|
static void init(void);
|
||||||
static int yday(const tm*);
|
|
||||||
|
|
||||||
static void ndate(SLONG, tm*);
|
|
||||||
static GDS_DATE nday(const tm*);
|
|
||||||
static void sanitize(TEXT*);
|
static void sanitize(TEXT*);
|
||||||
|
|
||||||
static void safe_concat_path(TEXT* destbuf, const TEXT* srcbuf);
|
static void safe_concat_path(TEXT* destbuf, const TEXT* srcbuf);
|
||||||
@ -495,12 +493,7 @@ void API_ROUTINE isc_decode_sql_date(const GDS_DATE* date, void* times_arg)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
tm* times = (struct tm*) times_arg;
|
tm* times = (struct tm*) times_arg;
|
||||||
memset(times, 0, sizeof(*times));
|
TimeStamp::decode_date(*date, times);
|
||||||
|
|
||||||
ndate(*date, times);
|
|
||||||
times->tm_yday = yday(times);
|
|
||||||
if ((times->tm_wday = (*date + 3) % 7) < 0)
|
|
||||||
times->tm_wday += 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -537,23 +530,12 @@ void API_ROUTINE isc_decode_timestamp(const GDS_TIMESTAMP* date, void* times_arg
|
|||||||
* Functional description
|
* Functional description
|
||||||
* Convert from internal timestamp format to UNIX time structure.
|
* Convert from internal timestamp format to UNIX time structure.
|
||||||
*
|
*
|
||||||
* Note: the date arguement is really an ISC_TIMESTAMP -- however the
|
* Note: This routine is intended only for public API use. Engine itself and
|
||||||
* definition of ISC_TIMESTAMP is not available from all the source
|
* utilities should be using TimeStamp class directly in type-safe manner.
|
||||||
* modules that need to use isc_encode_timestamp
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
tm* times = (struct tm*) times_arg;
|
|
||||||
memset(times, 0, sizeof(*times));
|
|
||||||
|
|
||||||
ndate(date->timestamp_date, times);
|
Firebird::TimeStamp(*date).decode(reinterpret_cast<tm*>(times_arg));
|
||||||
times->tm_yday = yday(times);
|
|
||||||
if ((times->tm_wday = (date->timestamp_date + 3) % 7) < 0)
|
|
||||||
times->tm_wday += 7;
|
|
||||||
|
|
||||||
const ULONG minutes = date->timestamp_time / (ISC_TIME_SECONDS_PRECISION * 60);
|
|
||||||
times->tm_hour = minutes / 60;
|
|
||||||
times->tm_min = minutes % 60;
|
|
||||||
times->tm_sec = (date->timestamp_time / ISC_TIME_SECONDS_PRECISION) % 60;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -593,7 +575,9 @@ void API_ROUTINE isc_encode_date(const void* times_arg, ISC_QUAD* date)
|
|||||||
* isc_encode_timestamp
|
* isc_encode_timestamp
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
isc_encode_timestamp(times_arg, (GDS_TIMESTAMP*) date);
|
Firebird::TimeStamp temp;
|
||||||
|
temp.encode(reinterpret_cast<const tm*>(times_arg));
|
||||||
|
*date = (ISC_QUAD&)temp.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -610,7 +594,7 @@ void API_ROUTINE isc_encode_sql_date(const void* times_arg, GDS_DATE* date)
|
|||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
*date = nday((const struct tm*) times_arg);
|
*date = TimeStamp::encode_date((const struct tm*) times_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -636,24 +620,20 @@ void API_ROUTINE isc_encode_timestamp(const void* times_arg, GDS_TIMESTAMP* date
|
|||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
*
|
*
|
||||||
* i s c _ e n c o d e _ t i m e s t a m p
|
* i s c _ e n c o d e _ d a t e
|
||||||
*
|
*
|
||||||
**************************************
|
**************************************
|
||||||
*
|
*
|
||||||
* Functional description
|
* Functional description
|
||||||
* Convert from UNIX time structure to internal timestamp format.
|
* Convert from UNIX time structure to internal timestamp format.
|
||||||
*
|
*
|
||||||
* Note: the date arguement is really an ISC_TIMESTAMP -- however the
|
* Note: This routine is intended only for public API use. Engine itself and
|
||||||
* definition of ISC_TIMESTAMP is not available from all the source
|
* utilities should be using TimeStamp class directly in type-safe manner.
|
||||||
* modules that need to use isc_encode_timestamp
|
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
const tm* times = (const struct tm*) times_arg;
|
Firebird::TimeStamp temp;
|
||||||
|
temp.encode(reinterpret_cast<const tm*>(times_arg));
|
||||||
date->timestamp_date = nday(times);
|
*date = temp.value();
|
||||||
date->timestamp_time =
|
|
||||||
((times->tm_hour * 60 + times->tm_min) * 60 +
|
|
||||||
times->tm_sec) * ISC_TIME_SECONDS_PRECISION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1125,15 +1105,14 @@ void API_ROUTINE gds__trace(const TEXT * text)
|
|||||||
|
|
||||||
const int days = now / SECS_PER_DAY;
|
const int days = now / SECS_PER_DAY;
|
||||||
int rem = now % SECS_PER_DAY;
|
int rem = now % SECS_PER_DAY;
|
||||||
|
|
||||||
tm today;
|
tm today;
|
||||||
|
TimeStamp::decode_date(days + TimeStamp::GDS_EPOCH_START, &today);
|
||||||
today.tm_hour = rem / SECS_PER_HOUR;
|
today.tm_hour = rem / SECS_PER_HOUR;
|
||||||
rem %= SECS_PER_HOUR;
|
rem %= SECS_PER_HOUR;
|
||||||
today.tm_min = rem / 60;
|
today.tm_min = rem / 60;
|
||||||
today.tm_sec = rem % 60;
|
today.tm_sec = rem % 60;
|
||||||
|
|
||||||
ndate(days + 40617 /* Number of first day of the Epoch in GDS counting */,
|
|
||||||
&today);
|
|
||||||
|
|
||||||
char buffer[1024]; // 1K should be enough for the trace message
|
char buffer[1024]; // 1K should be enough for the trace message
|
||||||
char* p = buffer;
|
char* p = buffer;
|
||||||
gds__ulstr(p, today.tm_year+1900, 4, '0'); p+=4;
|
gds__ulstr(p, today.tm_year+1900, 4, '0'); p+=4;
|
||||||
@ -3544,135 +3523,6 @@ static void init(void)
|
|||||||
/* V4_GLOBAL_MUTEX_UNLOCK; */
|
/* V4_GLOBAL_MUTEX_UNLOCK; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int yday(const struct tm* times)
|
|
||||||
{
|
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* y d a y
|
|
||||||
*
|
|
||||||
**************************************
|
|
||||||
*
|
|
||||||
* Functional description
|
|
||||||
* Convert a calendar date to the day-of-year.
|
|
||||||
*
|
|
||||||
* The unix time structure considers
|
|
||||||
* january 1 to be Year day 0, although it
|
|
||||||
* is day 1 of the month. (Note that QLI,
|
|
||||||
* when printing Year days takes the other
|
|
||||||
* view.)
|
|
||||||
*
|
|
||||||
**************************************/
|
|
||||||
SSHORT day = times->tm_mday;
|
|
||||||
const SSHORT month = times->tm_mon;
|
|
||||||
const SSHORT year = times->tm_year + 1900;
|
|
||||||
|
|
||||||
--day;
|
|
||||||
|
|
||||||
day += (214 * month + 3) / 7;
|
|
||||||
|
|
||||||
if (month < 2)
|
|
||||||
return day;
|
|
||||||
|
|
||||||
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
|
|
||||||
--day;
|
|
||||||
else
|
|
||||||
day -= 2;
|
|
||||||
|
|
||||||
return day;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void ndate(SLONG nday, tm* times)
|
|
||||||
{
|
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* n d a t e
|
|
||||||
*
|
|
||||||
**************************************
|
|
||||||
*
|
|
||||||
* Functional description
|
|
||||||
* Convert a numeric day to [day, month, year].
|
|
||||||
*
|
|
||||||
* Calenders are divided into 4 year cycles.
|
|
||||||
* 3 Non-Leap years, and 1 leap year.
|
|
||||||
* Each cycle takes 365*4 + 1 == 1461 days.
|
|
||||||
* There is a further cycle of 100 4 year cycles.
|
|
||||||
* Every 100 years, the normally expected leap year
|
|
||||||
* is not present. Every 400 years it is.
|
|
||||||
* This cycle takes 100 * 1461 - 3 == 146097 days
|
|
||||||
* The origin of the constant 2400001 is unknown.
|
|
||||||
* The origin of the constant 1721119 is unknown.
|
|
||||||
* The difference between 2400001 and 1721119 is the
|
|
||||||
* number of days From 0/0/0000 to our base date of
|
|
||||||
* 11/xx/1858. (678882)
|
|
||||||
* The origin of the constant 153 is unknown.
|
|
||||||
*
|
|
||||||
* This whole routine has problems with ndates
|
|
||||||
* less than -678882 (Approx 2/1/0000).
|
|
||||||
*
|
|
||||||
**************************************/
|
|
||||||
nday -= 1721119 - 2400001;
|
|
||||||
const SLONG century = (4 * nday - 1) / 146097;
|
|
||||||
nday = 4 * nday - 1 - 146097 * century;
|
|
||||||
SLONG day = nday / 4;
|
|
||||||
|
|
||||||
nday = (4 * day + 3) / 1461;
|
|
||||||
day = 4 * day + 3 - 1461 * nday;
|
|
||||||
day = (day + 4) / 4;
|
|
||||||
|
|
||||||
SLONG month = (5 * day - 3) / 153;
|
|
||||||
day = 5 * day - 3 - 153 * month;
|
|
||||||
day = (day + 5) / 5;
|
|
||||||
|
|
||||||
SLONG year = 100 * century + nday;
|
|
||||||
|
|
||||||
if (month < 10)
|
|
||||||
month += 3;
|
|
||||||
else {
|
|
||||||
month -= 9;
|
|
||||||
year += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
times->tm_mday = (int) day;
|
|
||||||
times->tm_mon = (int) month - 1;
|
|
||||||
times->tm_year = (int) year - 1900;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static GDS_DATE nday(const tm* times)
|
|
||||||
{
|
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* n d a y
|
|
||||||
*
|
|
||||||
**************************************
|
|
||||||
*
|
|
||||||
* Functional description
|
|
||||||
* Convert a calendar date to a numeric day
|
|
||||||
* (the number of days since the base date).
|
|
||||||
*
|
|
||||||
**************************************/
|
|
||||||
const SSHORT day = times->tm_mday;
|
|
||||||
SSHORT month = times->tm_mon + 1;
|
|
||||||
SSHORT year = times->tm_year + 1900;
|
|
||||||
|
|
||||||
if (month > 2)
|
|
||||||
month -= 3;
|
|
||||||
else {
|
|
||||||
month += 9;
|
|
||||||
year -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SLONG c = year / 100;
|
|
||||||
const SLONG ya = year - 100 * c;
|
|
||||||
|
|
||||||
return (GDS_DATE) (((SINT64) 146097 * c) / 4 +
|
|
||||||
(1461 * ya) / 4 +
|
|
||||||
(153 * month + 2) / 5 + day + 1721119 - 2400001);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void sanitize(TEXT* locale)
|
static void sanitize(TEXT* locale)
|
||||||
{
|
{
|
||||||
/**************************************
|
/**************************************
|
||||||
|
@ -585,8 +585,5 @@ void MOV_time_stamp(GDS_TIMESTAMP* date)
|
|||||||
* Get the current timestamp in gds format.
|
* Get the current timestamp in gds format.
|
||||||
*
|
*
|
||||||
**************************************/
|
**************************************/
|
||||||
if (!Firebird::TimeStamp().encode(date, false))
|
*date = Firebird::TimeStamp().value();
|
||||||
{
|
|
||||||
ERR_post(isc_date_range_exceeded, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user