From a7ead4ee184f1e9c9503710ac85d85e9af30803c Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Wed, 11 Jun 2014 16:41:34 -0400 Subject: [PATCH] work on datetime functionality --- include/xlnt/common/datetime.hpp | 12 ++++- source/cell.cpp | 13 ++--- source/datetime.cpp | 87 ++++++++++++++++++++++++++++++-- source/detail/cell_impl.cpp | 4 +- source/detail/cell_impl.hpp | 2 +- source/writer.cpp | 1 + tests/runner-autogen.cpp | 26 +++++----- tests/test_cell.hpp | 2 +- 8 files changed, 117 insertions(+), 30 deletions(-) diff --git a/include/xlnt/common/datetime.hpp b/include/xlnt/common/datetime.hpp index 5d768b5a..20fe9b5e 100644 --- a/include/xlnt/common/datetime.hpp +++ b/include/xlnt/common/datetime.hpp @@ -29,12 +29,16 @@ namespace xlnt { struct date { static date today(); + static date from_number(long double number); date(int year, int month, int day) : year(year), month(month), day(day) { } + double to_number() const; + bool operator==(const date &comparand) const; + int year; int month; int day; @@ -43,16 +47,16 @@ struct date struct time { static time now(); + static time from_number(long double number); time(int hour = 0, int minute = 0, int second = 0, int microsecond = 0) : hour(hour), minute(minute), second(second), microsecond(microsecond) { } - - explicit time(long double number); explicit time(const std::string &time_string); double to_number() const; + bool operator==(const time &comparand) const; int hour; int minute; @@ -63,12 +67,16 @@ struct time struct datetime { static datetime now(); + static datetime from_number(long double number); datetime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int microsecond = 0) : year(year), month(month), day(day), hour(hour), minute(minute), second(second), microsecond(microsecond) { } + double to_number() const; + bool operator==(const datetime &comparand) const; + int year; int month; int day; diff --git a/source/cell.cpp b/source/cell.cpp index 0f9e1e00..71c9db9f 100644 --- a/source/cell.cpp +++ b/source/cell.cpp @@ -276,17 +276,17 @@ bool cell::operator==(const char *comparand) const bool cell::operator==(const time &comparand) const { - return d_->type_ == type::numeric && time(d_->numeric_value).hour == comparand.hour; + return d_->type_ == type::numeric && time::from_number(d_->numeric_value) == comparand; } bool cell::operator==(const date &comparand) const { - return d_->type_ == type::numeric && date((int)d_->numeric_value, 0, 0).year == comparand.year; + return d_->type_ == type::numeric && date::from_number(d_->numeric_value) == comparand; } bool cell::operator==(const datetime &comparand) const { - return d_->type_ == type::numeric && datetime((int)d_->numeric_value, 0, 0).year == comparand.year; + return d_->type_ == type::numeric && datetime::from_number(d_->numeric_value) == comparand; } bool operator==(int comparand, const xlnt::cell &cell) @@ -448,14 +448,15 @@ cell &cell::operator=(const char *value) cell &cell::operator=(const time &value) { d_->type_ = type::numeric; - d_->numeric_value = value.hour; + d_->numeric_value = value.to_number(); + d_->is_date_ = true; return *this; } cell &cell::operator=(const date &value) { d_->type_ = type::numeric; - d_->numeric_value = value.year; + d_->numeric_value = value.to_number(); d_->is_date_ = true; return *this; } @@ -463,7 +464,7 @@ cell &cell::operator=(const date &value) cell &cell::operator=(const datetime &value) { d_->type_ = type::numeric; - d_->numeric_value = value.year; + d_->numeric_value = value.to_number(); d_->is_date_ = true; return *this; } diff --git a/source/datetime.cpp b/source/datetime.cpp index c297aa3a..158f35cb 100644 --- a/source/datetime.cpp +++ b/source/datetime.cpp @@ -5,18 +5,75 @@ namespace xlnt { -time::time(long double raw_time) : hour(0), minute(0), second(0), microsecond(0) +time time::from_number(long double raw_time) { double integer_part; double fractional_part = std::modf((double)raw_time, &integer_part); fractional_part *= 24; - hour = (int)fractional_part; + int hour = (int)fractional_part; fractional_part = 60 * (fractional_part - hour); - minute = (int)fractional_part; + int minute = (int)fractional_part; fractional_part = 60 * (fractional_part - minute); - second = (int)fractional_part; + int second = (int)fractional_part; fractional_part = 1000000 * (fractional_part - second); - microsecond = (int)fractional_part; + int microsecond = (int)fractional_part; + return time(hour, minute, second, microsecond); +} + +date date::from_number(long double number) +{ + int year = (int)number / 365; + number -= year * 365; + int month = (int)number / 30; + number -= month * 30; + int day = (int)number; + return date(year, month, day + 1); +} + +datetime datetime::from_number(long double raw_time) +{ + double integer_part; + double fractional_part = std::modf((double)raw_time, &integer_part); + fractional_part *= 24; + int hour = (int)fractional_part; + fractional_part = 60 * (fractional_part - hour); + int minute = (int)fractional_part; + fractional_part = 60 * (fractional_part - minute); + int second = (int)fractional_part; + fractional_part = 1000000 * (fractional_part - second); + int microsecond = (int)fractional_part; + int year = (int)integer_part / 365; + integer_part -= year * 365; + int month = (int)integer_part / 30; + integer_part -= month * 30; + int day = (int)integer_part; + return datetime(year + 1900, month, day + 1, hour, minute, second, microsecond); +} + +bool date::operator==(const date &comparand) const +{ + return year == comparand.year + && month == comparand.month + && day == comparand.day; +} + +bool time::operator==(const time &comparand) const +{ + return hour == comparand.hour + && minute == comparand.minute + && second == comparand.second + && microsecond == comparand.microsecond; +} + +bool datetime::operator==(const datetime &comparand) const +{ + return year == comparand.year + && month == comparand.month + && day == comparand.day + && hour == comparand.hour + && minute == comparand.minute + && second == comparand.second + && microsecond == comparand.microsecond; } time::time(const std::string &time_string) : hour(0), minute(0), second(0), microsecond(0) @@ -48,6 +105,26 @@ double time::to_number() const return number; } +double date::to_number() const +{ + double number = day + month * 30 + year * 365; + return number; +} + +double datetime::to_number() const +{ + double number = microsecond; + number /= 1000000; + number += second; + number /= 60; + number += minute; + number /= 60; + number += hour; + number /= 24; + number += (day - 1) + month * 30 + (year - 1900) * 365; + return number; +} + date date::today() { std::time_t raw_time = std::time(0); diff --git a/source/detail/cell_impl.cpp b/source/detail/cell_impl.cpp index b0c3642a..913c6e76 100644 --- a/source/detail/cell_impl.cpp +++ b/source/detail/cell_impl.cpp @@ -4,11 +4,11 @@ namespace xlnt { namespace detail { -cell_impl::cell_impl() : parent_(nullptr), type_(cell::type::null), column(0), row(0), style_(nullptr), merged(false) + cell_impl::cell_impl() : parent_(nullptr), type_(cell::type::null), column(0), row(0), style_(nullptr), merged(false), has_hyperlink_(false) { } -cell_impl::cell_impl(worksheet_impl *parent, int column_index, int row_index) : parent_(parent), type_(cell::type::null), column(column_index), row(row_index), style_(nullptr), merged(false) +cell_impl::cell_impl(worksheet_impl *parent, int column_index, int row_index) : parent_(parent), type_(cell::type::null), column(column_index), row(row_index), style_(nullptr), merged(false), has_hyperlink_(false) { } diff --git a/source/detail/cell_impl.hpp b/source/detail/cell_impl.hpp index 49a01126..423319e5 100644 --- a/source/detail/cell_impl.hpp +++ b/source/detail/cell_impl.hpp @@ -21,13 +21,13 @@ struct cell_impl cell::type type_; long double numeric_value; std::string string_value; - bool has_hyperlink_; relationship hyperlink_; column_t column; row_t row; style *style_; bool merged; bool is_date_; + bool has_hyperlink_; }; } // namespace detail diff --git a/source/writer.cpp b/source/writer.cpp index 9fe42a37..60924459 100644 --- a/source/writer.cpp +++ b/source/writer.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/tests/runner-autogen.cpp b/tests/runner-autogen.cpp index c6a6df00..1616a63c 100644 --- a/tests/runner-autogen.cpp +++ b/tests/runner-autogen.cpp @@ -21,7 +21,7 @@ int main( int argc, char *argv[] ) { return status; } bool suite_test_cell_init = false; -#include "/Users/thomas/Development/xlnt/tests/test_cell.hpp" +#include "/home/thomas/Development/xlnt/tests/test_cell.hpp" static test_cell suite_test_cell; @@ -238,7 +238,7 @@ public: void runTest() { suite_test_cell.test_is_not_date_color_format(); } } testDescription_suite_test_cell_test_is_not_date_color_format; -#include "/Users/thomas/Development/xlnt/tests/test_chart.hpp" +#include "/home/thomas/Development/xlnt/tests/test_chart.hpp" static test_chart suite_test_chart; @@ -329,7 +329,7 @@ public: void runTest() { suite_test_chart.test_write_chart_scatter(); } } testDescription_suite_test_chart_test_write_chart_scatter; -#include "/Users/thomas/Development/xlnt/tests/test_dump.hpp" +#include "/home/thomas/Development/xlnt/tests/test_dump.hpp" static test_dump suite_test_dump; @@ -366,7 +366,7 @@ public: void runTest() { suite_test_dump.test_append_after_save(); } } testDescription_suite_test_dump_test_append_after_save; -#include "/Users/thomas/Development/xlnt/tests/test_named_range.hpp" +#include "/home/thomas/Development/xlnt/tests/test_named_range.hpp" static test_named_range suite_test_named_range; @@ -457,7 +457,7 @@ public: void runTest() { suite_test_named_range.test_can_be_saved(); } } testDescription_suite_test_named_range_test_can_be_saved; -#include "/Users/thomas/Development/xlnt/tests/test_number_format.hpp" +#include "/home/thomas/Development/xlnt/tests/test_number_format.hpp" static test_number_format suite_test_number_format; @@ -560,7 +560,7 @@ public: void runTest() { suite_test_number_format.test_mac_date(); } } testDescription_suite_test_number_format_test_mac_date; -#include "/Users/thomas/Development/xlnt/tests/test_props.hpp" +#include "/home/thomas/Development/xlnt/tests/test_props.hpp" static test_props suite_test_props; @@ -603,7 +603,7 @@ public: void runTest() { suite_test_props.test_write_properties_app(); } } testDescription_suite_test_props_test_write_properties_app; -#include "/Users/thomas/Development/xlnt/tests/test_read.hpp" +#include "/home/thomas/Development/xlnt/tests/test_read.hpp" static test_read suite_test_read; @@ -736,7 +736,7 @@ public: void runTest() { suite_test_read.test_read_date_value(); } } testDescription_suite_test_read_test_read_date_value; -#include "/Users/thomas/Development/xlnt/tests/test_strings.hpp" +#include "/home/thomas/Development/xlnt/tests/test_strings.hpp" static test_strings suite_test_strings; @@ -767,7 +767,7 @@ public: void runTest() { suite_test_strings.test_formatted_string_table(); } } testDescription_suite_test_strings_test_formatted_string_table; -#include "/Users/thomas/Development/xlnt/tests/test_style.hpp" +#include "/home/thomas/Development/xlnt/tests/test_style.hpp" static test_style suite_test_style; @@ -864,7 +864,7 @@ public: void runTest() { suite_test_style.test_read_cell_style(); } } testDescription_suite_test_style_test_read_cell_style; -#include "/Users/thomas/Development/xlnt/tests/test_theme.hpp" +#include "/home/thomas/Development/xlnt/tests/test_theme.hpp" static test_theme suite_test_theme; @@ -877,7 +877,7 @@ public: void runTest() { suite_test_theme.test_write_theme(); } } testDescription_suite_test_theme_test_write_theme; -#include "/Users/thomas/Development/xlnt/tests/test_workbook.hpp" +#include "/home/thomas/Development/xlnt/tests/test_workbook.hpp" static test_workbook suite_test_workbook; @@ -1004,7 +1004,7 @@ public: void runTest() { suite_test_workbook.test_write_regular_float(); } } testDescription_suite_test_workbook_test_write_regular_float; -#include "/Users/thomas/Development/xlnt/tests/test_worksheet.hpp" +#include "/home/thomas/Development/xlnt/tests/test_worksheet.hpp" static test_worksheet suite_test_worksheet; @@ -1173,7 +1173,7 @@ public: void runTest() { suite_test_worksheet.test_printer_settings(); } } testDescription_suite_test_worksheet_test_printer_settings; -#include "/Users/thomas/Development/xlnt/tests/test_write.hpp" +#include "/home/thomas/Development/xlnt/tests/test_write.hpp" static test_write suite_test_write; diff --git a/tests/test_cell.hpp b/tests/test_cell.hpp index 5d8a1359..43c25b46 100644 --- a/tests/test_cell.hpp +++ b/tests/test_cell.hpp @@ -232,7 +232,7 @@ public: xlnt::worksheet ws = wb.create_sheet(); xlnt::cell cell(ws, "A1"); cell = "3.14%"; - TS_ASSERT_EQUALS(0.0314, cell.get_internal_value_numeric()); + TS_ASSERT_DELTA(0.0314, cell.get_internal_value_numeric(), 1e-7); } void test_insert_datetime()