Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FORMAT clause to convert datetime types to string and vice versa #2388 #7629

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 14 additions & 14 deletions src/common/TimeZoneUtil.cpp
Expand Up @@ -80,7 +80,6 @@ namespace

static const TimeZoneDesc* getDesc(USHORT timeZone);
static inline bool isOffset(USHORT timeZone);
static USHORT makeFromOffset(int sign, unsigned tzh, unsigned tzm);
static inline SSHORT offsetZoneToDisplacement(USHORT timeZone);
static inline USHORT displacementToOffsetZone(SSHORT displacement);
static int parseNumber(const char*& p, const char* end);
Expand Down Expand Up @@ -634,6 +633,20 @@ void TimeZoneUtil::extractOffset(const ISC_TIME_TZ& timeTz, SSHORT* offset)
extractOffset(tsTz, offset);
}

// Makes a time zone id from offsets.
USHORT TimeZoneUtil::makeFromOffset(int sign, unsigned tzh, unsigned tzm)
{
if (!TimeZoneUtil::isValidOffset(sign, tzh, tzm))
{
string str;
str.printf("%s%02u:%02u", (sign == -1 ? "-" : "+"), tzh, tzm);
status_exception::raise(Arg::Gds(isc_invalid_timezone_offset) << str);
}

return (USHORT)displacementToOffsetZone((tzh * 60 + tzm) * sign);
}


// Converts a time from local to UTC.
void TimeZoneUtil::localTimeToUtc(ISC_TIME& time, ISC_USHORT timeZone)
{
Expand Down Expand Up @@ -1153,19 +1166,6 @@ static inline bool isOffset(USHORT timeZone)
return timeZone <= ONE_DAY * 2;
}

// Makes a time zone id from offsets.
static USHORT makeFromOffset(int sign, unsigned tzh, unsigned tzm)
{
if (!TimeZoneUtil::isValidOffset(sign, tzh, tzm))
{
string str;
str.printf("%s%02u:%02u", (sign == -1 ? "-" : "+"), tzh, tzm);
status_exception::raise(Arg::Gds(isc_invalid_timezone_offset) << str);
}

return (USHORT)displacementToOffsetZone((tzh * 60 + tzm) * sign);
}

// Gets the displacement from a offset-based time zone id.
static inline SSHORT offsetZoneToDisplacement(USHORT timeZone)
{
Expand Down
2 changes: 2 additions & 0 deletions src/common/TimeZoneUtil.h
Expand Up @@ -97,6 +97,8 @@ class TimeZoneUtil
static void extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* offset);
static void extractOffset(const ISC_TIME_TZ& timeTz, SSHORT* offset);

static USHORT makeFromOffset(int sign, unsigned tzh, unsigned tzm);

static void localTimeToUtc(ISC_TIME& time, ISC_USHORT timeZone);
static void localTimeToUtc(ISC_TIME_TZ& timeTz);

Expand Down
74 changes: 74 additions & 0 deletions src/common/classes/NoThrowTimeStamp.cpp
Expand Up @@ -337,6 +337,80 @@ void NoThrowTimeStamp::round_time(ISC_TIME &ntime, const int precision)
ntime -= (ntime % period);
}

int NoThrowTimeStamp::convertGregorianDateToWeekDate(const struct tm& times)
{
// Algorithm for Converting Gregorian Dates to ISO 8601 Week Date by Rick McCarty, 1999
// http://personal.ecu.edu/mccartyr/ISOwdALG.txt

const int y = times.tm_year + 1900;
const int dayOfYearNumber = times.tm_yday + 1;

// Find the jan1Weekday for y (Monday=1, Sunday=7)
const int yy = (y - 1) % 100;
const int c = (y - 1) - yy;
const int g = yy + yy / 4;
const int jan1Weekday = 1 + (((((c / 100) % 4) * 5) + g) % 7);

// Find the weekday for y m d
const int h = dayOfYearNumber + (jan1Weekday - 1);
const int weekday = 1 + ((h - 1) % 7);

// Find if y m d falls in yearNumber y-1, weekNumber 52 or 53
int yearNumber, weekNumber;

if ((dayOfYearNumber <= (8 - jan1Weekday)) && (jan1Weekday > 4))
{
yearNumber = y - 1;
weekNumber = ((jan1Weekday == 5) || ((jan1Weekday == 6) &&
isLeapYear(yearNumber))) ? 53 : 52;
}
else
{
yearNumber = y;

// Find if y m d falls in yearNumber y+1, weekNumber 1
int i = isLeapYear(y) ? 366 : 365;

if ((i - dayOfYearNumber) < (4 - weekday))
{
yearNumber = y + 1;
weekNumber = 1;
}
}

// Find if y m d falls in yearNumber y, weekNumber 1 through 53
if (yearNumber == y)
{
int j = dayOfYearNumber + (7 - weekday) + (jan1Weekday - 1);
weekNumber = j / 7;
if (jan1Weekday > 4)
weekNumber--;
}

return weekNumber;
}

int NoThrowTimeStamp::convertGregorianDateToJulianDate(int year, int month, int day)
{
int jdn = (1461 * (year + 4800 + (month - 14)/12))/4 + (367 * (month - 2 - 12 * ((month - 14)/12)))
/ 12 - (3 * ((year + 4900 + (month - 14)/12)/100))/4 + day - 32075;
return jdn;
}

void NoThrowTimeStamp::convertJulianDateToGregorianDate(int jdn, int& outYear, int& outMonth, int& outDay)
{
int a = jdn + 32044;
int b = (4 * a +3 ) / 146097;
int c = a - (146097 * b) / 4;
int d = (4 * c + 3) / 1461;
int e = c - (1461 * d) / 4;
int m = (5 * e + 2) / 153;

outDay = e - (153 * m + 2) / 5 + 1;
outMonth = m + 3 - 12 * (m / 10);
outYear = 100 * b + d - 4800 + (m / 10);
}

// Encode timestamp from UNIX datetime structure
void NoThrowTimeStamp::encode(const struct tm* times, int fractions)
{
Expand Down
4 changes: 4 additions & 0 deletions src/common/classes/NoThrowTimeStamp.h
Expand Up @@ -168,6 +168,10 @@ class NoThrowTimeStamp
static void add10msec(ISC_TIMESTAMP* v, SINT64 msec, SINT64 multiplier);
static void round_time(ISC_TIME& ntime, const int precision);

static int convertGregorianDateToWeekDate(const struct tm& times);
static int convertGregorianDateToJulianDate(int year, int month, int day);
static void convertJulianDateToGregorianDate(int jdn, int& outYear, int& outMonth, int& outDay);

static inline bool isLeapYear(const int year) throw()
{
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
Expand Down
26 changes: 26 additions & 0 deletions src/common/common.h
Expand Up @@ -993,6 +993,32 @@ static const TEXT* const FB_LONG_MONTHS_UPPER[] =
0
};

// Starts with SUNDAY cuz tm.tm_wday starts with it
static const TEXT FB_SHORT_DAYS[][4] =
{
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"\0"
};

// Starts with SUNDAY cuz tm.tm_wday starts with it
static const TEXT* const FB_LONG_DAYS_UPPER[] =
{
"SUNDAY",
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"\0"
};

const FB_SIZE_T FB_MAX_SIZEOF = ~FB_SIZE_T(0); // Assume FB_SIZE_T is unsigned

inline FB_SIZE_T fb_strlen(const char* str)
Expand Down