Skip to content

Commit

Permalink
Use printf to add extra zeros
Browse files Browse the repository at this point in the history
Also add extra zeros to the year patterns.
  • Loading branch information
Artyom Ivanov committed Aug 7, 2023
1 parent 7be7e1c commit 9b4f135
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 47 deletions.
16 changes: 8 additions & 8 deletions doc/README.cast.format.md
Expand Up @@ -3,11 +3,11 @@
The following flags are currently implemented for datetime to string conversion:
| Format Pattern | Description |
| -------------- | ----------- |
| YEAR | Year |
| YYYY | Last 4 digits of Year |
| YYY | Last 3 digits of Year |
| YY | Last 2 digits of Year |
| Y | Last 1 digits of Year |
| YEAR | Year (1 - 9999) |
| YYYY | Last 4 digits of Year (0001 - 9999) |
| YYY | Last 3 digits of Year (000 - 999) |
| YY | Last 2 digits of Year (00 - 99) |
| Y | Last 1 digits of Year (0 - 9) |
| Q | Quarter of the Year (1 - 4) |
| MM | Month (01 - 12) |
| MON | Short Month name (Apr) |
Expand Down Expand Up @@ -48,10 +48,10 @@ SELECT CAST(CURRENT_TIMESTAMP AS VARCHAR(50) FORMAT 'YEARMMDD HH24MISS') FROM RD
=========================
20230719 161757
```
However, be careful with patterns like `DDDDD`, it will be interpreted as `DDD` + `DD`.
However, be careful with patterns like `DDDDD`, it will be interpreted as `DDD` + `DD`.

It is possible to insert raw text into a format string with `""`: `... FORMAT '"Today is" DAY'` - Today is MONDAY. To add `"` in output raw string use `\"` (to print `\` use `\\`).
Also the format is case-insensitive, so `YYYY-MM` == `yyyy-mm`.
It is possible to insert raw text into a format string with `""`: `... FORMAT '"Today is" DAY'` - Today is MONDAY. To add `"` in output raw string use `\"` (to print `\` use `\\`).
Also the format is case-insensitive, so `YYYY-MM` == `yyyy-mm`.
Example:
```
SELECT CAST(CURRENT_TIMESTAMP AS VARCHAR(45) FORMAT 'DD.MM.YEAR HH24:MI:SS "is" J "Julian day"') FROM RDB$DATABASE;
Expand Down
50 changes: 13 additions & 37 deletions src/common/cvt.cpp
Expand Up @@ -1185,11 +1185,11 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
if (pattern == "Y")
patternResult.printf("%d", year % 10);
else if (pattern == "YY")
patternResult.printf("%d", year % 100);
patternResult.printf("%02d", year % 100);
else if (pattern == "YYY")
patternResult.printf("%d", year % 1000);
patternResult.printf("%03d", year % 1000);
else if (pattern == "YYYY")
patternResult.printf("%d", year % 10000);
patternResult.printf("%04d", year % 10000);
else if (pattern == "YEAR")
patternResult.printf("%d", year);
break;
Expand All @@ -1211,18 +1211,14 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
{
date_type_check(ExpectedDateType::TIME, desc, pattern, cb);

const char* printfFormat = times.tm_min < 10 ? "0%d" : "%d";
patternResult.printf(printfFormat, times.tm_min);
patternResult.printf("%02d", times.tm_min);
break;
}

date_type_check(ExpectedDateType::DATE, desc, pattern, cb);

if (pattern == "MM")
{
const char* printfFormat = times.tm_mon + 1 < 10 ? "0%d" : "%d";
patternResult.printf(printfFormat, (times.tm_mon + 1));
}
patternResult.printf("%02d", (times.tm_mon + 1));
else if (pattern == "MON")
patternResult.printf("%s", FB_SHORT_MONTHS[times.tm_mon]);
else if (pattern == "MONTH")
Expand Down Expand Up @@ -1250,8 +1246,7 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
else if (pattern == "WW")
{
int week = NoThrowTimeStamp::convertGregorianDateToWeekDate(times);
const char* printfFormat = week < 10 ? "0%d" : "%d";
patternResult.printf(printfFormat, week);
patternResult.printf("%02d", week);
}
break;

Expand All @@ -1263,21 +1258,11 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
else if (pattern == "DAY")
patternResult.printf("%s", FB_LONG_DAYS_UPPER[times.tm_wday]);
else if (pattern == "DD")
{
const char* printfFormat = times.tm_mday < 10 ? "0%d" : "%d";
patternResult.printf(printfFormat, times.tm_mday);
}
patternResult.printf("%02d", times.tm_mday);
else if (pattern == "DDD")
{
int daysInYear = times.tm_yday + 1;
const char* printfFormat = "%d";

if (daysInYear < 10)
printfFormat = "00%d";
else if (daysInYear < 100)
printfFormat = "0%d";

patternResult.printf(printfFormat, daysInYear);
patternResult.printf("%03d", daysInYear);
}
else if (pattern == "DY")
patternResult.printf("%s", FB_SHORT_DAYS[times.tm_wday]);
Expand Down Expand Up @@ -1317,24 +1302,17 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
hours = 12;
}

const char* printfFormat = hours < 10 ? "0%d %s" : "%d %s";
patternResult.printf(printfFormat, hours, period);
patternResult.printf("%02d %s", hours, period);
}
else if (pattern == "HH24")
{
const char* printfFormat = times.tm_hour < 10 ? "0%d" : "%d";
patternResult.printf(printfFormat, times.tm_hour);
}
patternResult.printf("%02d", times.tm_hour);
break;

case 'S':
date_type_check(ExpectedDateType::TIME, desc, pattern, cb);

if (pattern == "SS")
{
const char* printfFormat = times.tm_sec < 10 ? "0%d" : "%d";
patternResult.printf(printfFormat, times.tm_sec);
}
patternResult.printf("%02d", times.tm_sec);
else if (pattern == "SSSSS")
{
int secondsInDay = times.tm_hour * 60 * 60 + times.tm_min * 60 + times.tm_sec;
Expand Down Expand Up @@ -1375,7 +1353,7 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
int timezoneSign = sign(timezoneOffset);
SSHORT offsetInHours = abs(timezoneOffset / 60);

string printfFormat = offsetInHours < 10 ? "0%d" : "%d";
string printfFormat = "%02d";

if (previousPattern != "TZM")
{
Expand All @@ -1393,7 +1371,7 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
int timezoneSign = sign(timezoneOffset);
SSHORT offsetInMinutes = abs(timezoneOffset % 60);

string printfFormat = offsetInMinutes < 10 ? "0%d" : "%d";
string printfFormat = "%02d";

if (previousPattern != "TZH")
{
Expand All @@ -1406,9 +1384,7 @@ static string datetime_to_format_string_pattern_matcher(const dsc* desc, std::st
patternResult.printf(printfFormat.c_str(), offsetInMinutes);
}
else if (pattern == "TZR")
{
patternResult = extract_timezone_name(desc);
}
break;

default:
Expand Down
4 changes: 2 additions & 2 deletions src/common/tests/CvtTest.cpp
Expand Up @@ -35,11 +35,11 @@ BOOST_AUTO_TEST_SUITE(FunctionalTest)

BOOST_AUTO_TEST_CASE(CVTDatetimeToFormatStringTest_DATE)
{
testCVTDatetimeToFormatString(createDate(1, 1, 1), "YEAR.YYYY.YYY.YY.Y", "1.1.1.1.1", cb);
testCVTDatetimeToFormatString(createDate(1, 1, 1), "YEAR.YYYY.YYY.YY.Y", "1.0001.001.01.1", cb);
testCVTDatetimeToFormatString(createDate(1234, 1, 1), "YEAR.YYYY.YYY.YY.Y", "1234.1234.234.34.4", cb);
testCVTDatetimeToFormatString(createDate(9999, 1, 1), "YEAR.YYYY.YYY.YY.Y", "9999.9999.999.99.9", cb);

testCVTDatetimeToFormatString(createDate(1, 1, 1), "YEAR.YYYY.YYY.YY.Y", "1.1.1.1.1", cb);
testCVTDatetimeToFormatString(createDate(1, 1, 1), "YEAR.YYYY.YYY.YY.Y", "1.0001.001.01.1", cb);
testCVTDatetimeToFormatString(createDate(1234, 1, 1), "YEAR.YYYY.YYY.YY.Y", "1234.1234.234.34.4", cb);
testCVTDatetimeToFormatString(createDate(9999, 1, 1), "YEAR.YYYY.YYY.YY.Y", "9999.9999.999.99.9", cb);

Expand Down

0 comments on commit 9b4f135

Please sign in to comment.