Rewrote the way date and time I/O is managed
This commit is contained in:
parent
588f2ef2f5
commit
fc84eeb358
17 changed files with 361 additions and 133 deletions
|
|
@ -127,7 +127,7 @@ void annotation_t::print(std::ostream& out, bool keep_base) const
|
|||
<< '}';
|
||||
|
||||
if (date)
|
||||
out << " [" << format_date(*date, string("%Y/%m/%d")) << ']';
|
||||
out << " [" << format_date(*date, FMT_WRITTEN) << ']';
|
||||
|
||||
if (tag)
|
||||
out << " (" << *tag << ')';
|
||||
|
|
|
|||
|
|
@ -531,15 +531,14 @@ void subtotal_posts::report_subtotal(const char * spec_fmt,
|
|||
|
||||
std::ostringstream out_date;
|
||||
if (spec_fmt) {
|
||||
out_date << format_date(*range_finish, string(spec_fmt));
|
||||
out_date << format_date(*range_finish, FMT_CUSTOM, spec_fmt);
|
||||
}
|
||||
else if (date_format) {
|
||||
string fmt = "- ";
|
||||
fmt += *date_format;
|
||||
out_date << format_date(*range_finish, string(fmt));
|
||||
out_date << "- " << format_date(*range_finish, FMT_CUSTOM,
|
||||
date_format->c_str());
|
||||
}
|
||||
else {
|
||||
out_date << format_date(*range_finish, std::string("- ") + output_date_format);
|
||||
out_date << "- " << format_date(*range_finish);
|
||||
}
|
||||
|
||||
xact_temps.push_back(xact_t());
|
||||
|
|
|
|||
|
|
@ -321,11 +321,11 @@ void generate_posts_iterator::generate_note(std::ostream& out)
|
|||
|
||||
void generate_posts_iterator::generate_xact(std::ostream& out)
|
||||
{
|
||||
out << format_date(next_date, string("%Y/%m/%d"));
|
||||
out << format_date(next_date, FMT_WRITTEN);
|
||||
next_date += gregorian::days(six_gen());
|
||||
if (truth_gen()) {
|
||||
out << '=';
|
||||
out << format_date(next_eff_date, string("%Y/%m/%d"));
|
||||
out << format_date(next_eff_date, FMT_WRITTEN);
|
||||
next_eff_date += gregorian::days(six_gen());
|
||||
}
|
||||
out << ' ';
|
||||
|
|
|
|||
|
|
@ -433,8 +433,10 @@ void global_scope_t::normalize_report_options(const string& verb)
|
|||
rep.session.commodity_pool->price_db = none;
|
||||
|
||||
if (rep.HANDLED(date_format_)) {
|
||||
output_datetime_format = rep.HANDLER(date_format_).str() + " %H:%M:%S";
|
||||
output_date_format = rep.HANDLER(date_format_).str();
|
||||
set_date_format(rep.HANDLER(date_format_).str().c_str());
|
||||
}
|
||||
if (rep.HANDLED(datetime_format_)) {
|
||||
set_datetime_format(rep.HANDLER(datetime_format_).str().c_str());
|
||||
}
|
||||
if (rep.HANDLED(start_of_week_)) {
|
||||
if (optional<date_time::weekdays> weekday =
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ commodity_quote_from_script(commodity_t& commodity,
|
|||
std::ios_base::out | std::ios_base::app);
|
||||
#endif
|
||||
database << "P "
|
||||
<< format_datetime(point->when, string("%Y/%m/%d %H:%M:%S"))
|
||||
<< format_datetime(point->when, FMT_WRITTEN)
|
||||
<< " " << commodity.symbol()
|
||||
<< " " << point->price
|
||||
<< std::endl;
|
||||
|
|
|
|||
|
|
@ -263,9 +263,12 @@ value_t report_t::fn_join(call_scope_t& scope)
|
|||
|
||||
value_t report_t::fn_format_date(call_scope_t& scope)
|
||||
{
|
||||
interactive_t args(scope, "ds");
|
||||
return string_value(format_date(args.get<date_t>(0),
|
||||
args.get<string>(1)));
|
||||
interactive_t args(scope, "d&s");
|
||||
if (args.has(1))
|
||||
return string_value(format_date(args.get<date_t>(0), FMT_CUSTOM,
|
||||
args.get<string>(1).c_str()));
|
||||
else
|
||||
return string_value(format_date(args.get<date_t>(0), FMT_PRINTED));
|
||||
}
|
||||
|
||||
value_t report_t::fn_ansify_if(call_scope_t& scope)
|
||||
|
|
@ -521,6 +524,7 @@ option_t<report_t> * report_t::lookup_option(const char * p)
|
|||
case 'd':
|
||||
OPT(daily);
|
||||
else OPT(date_format_);
|
||||
else OPT(datetime_format_);
|
||||
else OPT(depth_);
|
||||
else OPT(deviation);
|
||||
else OPT_(display_);
|
||||
|
|
|
|||
14
src/report.h
14
src/report.h
|
|
@ -218,6 +218,7 @@ public:
|
|||
HANDLER(current).report(out);
|
||||
HANDLER(daily).report(out);
|
||||
HANDLER(date_format_).report(out);
|
||||
HANDLER(datetime_format_).report(out);
|
||||
HANDLER(depth_).report(out);
|
||||
HANDLER(deviation).report(out);
|
||||
HANDLER(display_).report(out);
|
||||
|
|
@ -412,10 +413,8 @@ public:
|
|||
parent->HANDLER(period_).on(string("--daily"), "daily");
|
||||
});
|
||||
|
||||
OPTION__(report_t, date_format_, // -y
|
||||
CTOR(report_t, date_format_) {
|
||||
on(none, "%y-%b-%d");
|
||||
});
|
||||
OPTION(report_t, date_format_);
|
||||
OPTION(report_t, datetime_format_);
|
||||
|
||||
OPTION_(report_t, depth_, DO_(scope) {
|
||||
interactive_t args(scope, "sl");
|
||||
|
|
@ -633,9 +632,9 @@ public:
|
|||
|
||||
OPTION__(report_t, print_format_, CTOR(report_t, print_format_) {
|
||||
on(none,
|
||||
"%(format_date(xact.date, \"%Y/%m/%d\"))"
|
||||
"%(xact.date)"
|
||||
"%(!effective & xact.effective_date ?"
|
||||
" \"=\" + format_date(xact.effective_date, \"%Y/%m/%d\") : \"\")"
|
||||
" \"=\" + xact.effective_date : \"\")"
|
||||
"%(xact.cleared ? \" *\" : (xact.pending ? \" !\" : \"\"))"
|
||||
"%(code ? \" (\" + code + \")\" :"
|
||||
" \"\") %(payee)%(xact.comment)\n"
|
||||
|
|
@ -673,7 +672,8 @@ public:
|
|||
|
||||
OPTION__(report_t, register_format_, CTOR(report_t, register_format_) {
|
||||
on(none,
|
||||
"%(ansify_if(justify(date, date_width), green if color & date > today))"
|
||||
"%(ansify_if(justify(format_date(date), date_width), green "
|
||||
" if color & date > today))"
|
||||
" %(ansify_if(justify(truncated(payee, payee_width), payee_width), "
|
||||
" bold if color & !cleared))"
|
||||
" %(ansify_if(justify(truncated(account, account_width, abbrev_len), "
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ namespace ledger {
|
|||
void set_session_context(session_t * session)
|
||||
{
|
||||
if (session) {
|
||||
times_initialize();
|
||||
amount_t::initialize(session->commodity_pool);
|
||||
|
||||
// jww (2009-02-04): Is amount_t the right place for parse_conversion to
|
||||
|
|
@ -57,6 +58,7 @@ void set_session_context(session_t * session)
|
|||
else if (! session) {
|
||||
value_t::shutdown();
|
||||
amount_t::shutdown();
|
||||
times_shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ public:
|
|||
});
|
||||
|
||||
OPTION_(session_t, input_date_format_, DO_(args) {
|
||||
// This changes the global variable inside times.h, which affects the
|
||||
// basic date parser
|
||||
input_date_format = args[1].as_string();
|
||||
// This changes static variables inside times.h, which affects the basic
|
||||
// date parser.
|
||||
set_input_date_format(args[1].as_string().c_str());
|
||||
});
|
||||
|
||||
OPTION(session_t, price_db_);
|
||||
|
|
|
|||
351
src/times.cc
351
src/times.cc
|
|
@ -35,55 +35,177 @@
|
|||
|
||||
namespace ledger {
|
||||
|
||||
date_time::weekdays start_of_week = gregorian::Sunday;
|
||||
optional<std::string> input_date_format;
|
||||
std::string output_datetime_format = "%Y-%m-%d %H:%M:%S";
|
||||
std::string output_date_format = "%Y-%m-%d";
|
||||
date_time::weekdays start_of_week = gregorian::Sunday;
|
||||
|
||||
//#define USE_BOOST_FACETS 1
|
||||
|
||||
namespace {
|
||||
struct date_format_t {
|
||||
const char * format;
|
||||
bool has_year;
|
||||
date_format_t(const char * _format, bool _has_year)
|
||||
: format(_format), has_year(_has_year) {}
|
||||
};
|
||||
|
||||
const date_format_t formats[] = {
|
||||
date_format_t("%m/%d", false),
|
||||
date_format_t("%Y/%m/%d", true),
|
||||
date_format_t("%Y/%m", true),
|
||||
date_format_t("%y/%m/%d", true),
|
||||
date_format_t("%m.%d", false),
|
||||
date_format_t("%Y.%m.%d", true),
|
||||
date_format_t("%Y.%m", true),
|
||||
date_format_t("%y.%m.%d", true),
|
||||
date_format_t("%m-%d", false),
|
||||
date_format_t("%Y-%m-%d", true),
|
||||
date_format_t("%Y-%m", true),
|
||||
date_format_t("%y-%m-%d", true)
|
||||
};
|
||||
|
||||
date_t parse_date_mask_routine(const char * date_str, const date_format_t& df,
|
||||
optional<date_t::year_type> year, bool& saw_year)
|
||||
template <typename T, typename InputFacetType, typename OutputFacetType>
|
||||
class temporal_io_t : public noncopyable
|
||||
{
|
||||
std::string str(date_str);
|
||||
const char * fmt_str;
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
std::istringstream input_stream;
|
||||
std::ostringstream output_stream;
|
||||
InputFacetType * input_facet;
|
||||
OutputFacetType * output_facet;
|
||||
std::string temp_string;
|
||||
#endif
|
||||
|
||||
gregorian::date_input_facet * facet(new gregorian::date_input_facet(df.format));
|
||||
std::istringstream sstr(str);
|
||||
sstr.imbue(std::locale(sstr.getloc(), facet));
|
||||
public:
|
||||
bool has_year;
|
||||
bool input;
|
||||
|
||||
temporal_io_t(const char * _fmt_str, bool _input)
|
||||
: fmt_str(_fmt_str), has_year(icontains(fmt_str, "%y")),
|
||||
input(_input) {
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
if (input) {
|
||||
input_facet = new InputFacetType(fmt_str);
|
||||
input_stream.imbue(std::locale(std::locale::classic(), input_facet));
|
||||
} else {
|
||||
output_facet = new OutputFacetType(fmt_str);
|
||||
output_stream.imbue(std::locale(std::locale::classic(), output_facet));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_format(const char * fmt) {
|
||||
fmt_str = fmt;
|
||||
has_year = icontains(fmt_str, "%y");
|
||||
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
if (input)
|
||||
input_facet->format(fmt_str);
|
||||
else
|
||||
output_facet->format(fmt_str);
|
||||
#endif
|
||||
}
|
||||
|
||||
T parse(const char * str) {
|
||||
}
|
||||
|
||||
std::string format(const T& when) {
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
output_stream.str(temp_string);
|
||||
output_stream.seekp(std::ios_base::beg);
|
||||
output_stream.clear();
|
||||
output_stream << when;
|
||||
return output_stream.str();
|
||||
#else
|
||||
std::tm data(to_tm(when));
|
||||
char buf[128];
|
||||
std::strftime(buf, 127, fmt_str, &data);
|
||||
return buf;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
datetime_t temporal_io_t<datetime_t, posix_time::time_input_facet,
|
||||
posix_time::time_facet>
|
||||
::parse(const char * str)
|
||||
{
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
input_stream.seekg(std::ios_base::beg);
|
||||
input_stream.clear();
|
||||
input_stream.str(str);
|
||||
|
||||
datetime_t when;
|
||||
input_stream >> when;
|
||||
#if defined(DEBUG_ON)
|
||||
if (when.is_not_a_date_time())
|
||||
DEBUG("times.parse", "Failed to parse '" << str
|
||||
<< "' using pattern '" << fmt_str << "'");
|
||||
#endif
|
||||
|
||||
if (! when.is_not_a_date_time() &&
|
||||
input_stream.good() && ! input_stream.eof() &&
|
||||
input_stream.peek() != EOF)
|
||||
return datetime_t();
|
||||
return when;
|
||||
#else
|
||||
std::tm data;
|
||||
std::memset(&data, 0, sizeof(std::tm));
|
||||
if (strptime(str, fmt_str, &data))
|
||||
return posix_time::ptime_from_tm(data);
|
||||
else
|
||||
return datetime_t();
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
date_t temporal_io_t<date_t, gregorian::date_input_facet,
|
||||
gregorian::date_facet>
|
||||
::parse(const char * str)
|
||||
{
|
||||
#if defined(USE_BOOST_FACETS)
|
||||
input_stream.seekg(std::ios_base::beg);
|
||||
input_stream.clear();
|
||||
input_stream.str(str);
|
||||
|
||||
date_t when;
|
||||
input_stream >> when;
|
||||
#if defined(DEBUG_ON)
|
||||
if (when.is_not_a_date())
|
||||
DEBUG("times.parse", "Failed to parse '" << str
|
||||
<< "' using pattern '" << fmt_str << "'");
|
||||
#endif
|
||||
|
||||
if (! when.is_not_a_date() &&
|
||||
input_stream.good() && ! input_stream.eof() &&
|
||||
input_stream.peek() != EOF)
|
||||
return date_t();
|
||||
return when;
|
||||
#else
|
||||
std::tm data;
|
||||
std::memset(&data, 0, sizeof(std::tm));
|
||||
data.tm_mday = 1; // some formats have no day
|
||||
if (strptime(str, fmt_str, &data))
|
||||
return gregorian::date_from_tm(data);
|
||||
else
|
||||
return date_t();
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef temporal_io_t<datetime_t, posix_time::time_input_facet,
|
||||
posix_time::time_facet> datetime_io_t;
|
||||
typedef temporal_io_t<date_t, gregorian::date_input_facet,
|
||||
gregorian::date_facet> date_io_t;
|
||||
|
||||
std::auto_ptr<datetime_io_t> written_datetime_io;
|
||||
std::auto_ptr<datetime_io_t> printed_datetime_io;
|
||||
std::auto_ptr<date_io_t> input_date_io;
|
||||
std::auto_ptr<date_io_t> written_date_io;
|
||||
std::auto_ptr<date_io_t> printed_date_io;
|
||||
|
||||
std::vector<shared_ptr<date_io_t> > readers;
|
||||
|
||||
date_t parse_date_mask_routine(const char * date_str, date_io_t& io,
|
||||
optional<date_t::year_type> year,
|
||||
bool& saw_year)
|
||||
{
|
||||
date_t when;
|
||||
sstr >> when;
|
||||
|
||||
if (std::strchr(date_str, '/')) {
|
||||
when = io.parse(date_str);
|
||||
} else {
|
||||
char buf[128];
|
||||
VERIFY(std::strlen(date_str) < 127);
|
||||
std::strcpy(buf, date_str);
|
||||
|
||||
for (char * p = buf; *p; p++)
|
||||
if (*p == '.' || *p == '-')
|
||||
*p = '/';
|
||||
|
||||
when = io.parse(buf);
|
||||
}
|
||||
|
||||
if (! when.is_not_a_date()) {
|
||||
if (sstr.good() && ! sstr.eof() && sstr.peek() != EOF)
|
||||
return date_t();
|
||||
|
||||
DEBUG("times.parse", "Parsed date string: " << date_str);
|
||||
DEBUG("times.parse", "Parsed result is: " << when);
|
||||
DEBUG("times.parse", "Format used was: " << df.format);
|
||||
DEBUG("times.parse", "Parsed result is: " << when);
|
||||
|
||||
if (! df.has_year) {
|
||||
if (! io.has_year) {
|
||||
saw_year = false;
|
||||
|
||||
when = date_t(year ? *year : CURRENT_DATE().year(),
|
||||
|
|
@ -98,25 +220,24 @@ namespace {
|
|||
return when;
|
||||
}
|
||||
|
||||
date_t parse_date_mask(const char * date_str, optional<date_t::year_type> year,
|
||||
bool& saw_year)
|
||||
date_t parse_date_mask(const char * date_str,
|
||||
optional<date_t::year_type> year, bool& saw_year)
|
||||
{
|
||||
if (input_date_format) {
|
||||
date_format_t df(input_date_format->c_str(), true);
|
||||
if (! icontains(*input_date_format, "%y"))
|
||||
df.has_year = false;
|
||||
date_t when = parse_date_mask_routine(date_str, df, year, saw_year);
|
||||
if (input_date_io.get()) {
|
||||
date_t when = parse_date_mask_routine(date_str, *input_date_io.get(),
|
||||
year, saw_year);
|
||||
if (! when.is_not_a_date())
|
||||
return when;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < (sizeof(formats) / sizeof(date_format_t)); i++) {
|
||||
date_t when = parse_date_mask_routine(date_str, formats[i], year,
|
||||
saw_year);
|
||||
foreach (shared_ptr<date_io_t>& reader, readers) {
|
||||
date_t when = parse_date_mask_routine(date_str, *reader.get(),
|
||||
year, saw_year);
|
||||
if (! when.is_not_a_date())
|
||||
return when;
|
||||
}
|
||||
|
||||
throw_(date_error, _("Invalid date: %1") << date_str);
|
||||
return date_t();
|
||||
}
|
||||
}
|
||||
|
|
@ -174,16 +295,7 @@ string_to_month_of_year(const std::string& str)
|
|||
|
||||
datetime_t parse_datetime(const char * str, optional<date_t::year_type>)
|
||||
{
|
||||
posix_time::time_input_facet * facet
|
||||
(new posix_time::time_input_facet("%Y/%m/%d %H:%M:%S"));
|
||||
|
||||
std::string temp(str);
|
||||
std::istringstream sstr(temp);
|
||||
sstr.imbue(std::locale(sstr.getloc(), facet));
|
||||
|
||||
datetime_t when;
|
||||
sstr >> when;
|
||||
return when;
|
||||
return written_datetime_io->parse(str);
|
||||
}
|
||||
|
||||
date_t parse_date(const char * str, optional<date_t::year_type> current_year)
|
||||
|
|
@ -481,7 +593,7 @@ namespace {
|
|||
|
||||
inline void read_lower_word(std::istream& in, string& word) {
|
||||
in >> word;
|
||||
for (int i = 0, l = word.length(); i < l; i++)
|
||||
for (string::size_type i = 0, l = word.length(); i < l; i++)
|
||||
word[i] = static_cast<char>(std::tolower(word[i]));
|
||||
}
|
||||
|
||||
|
|
@ -662,4 +774,123 @@ void date_interval_t::parse(std::istream& in)
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
typedef std::map<std::string, datetime_io_t *> datetime_io_map;
|
||||
typedef std::map<std::string, date_io_t *> date_io_map;
|
||||
|
||||
datetime_io_map temp_datetime_io;
|
||||
date_io_map temp_date_io;
|
||||
}
|
||||
|
||||
std::string format_datetime(const datetime_t& when,
|
||||
const format_type_t format_type,
|
||||
const optional<const char *>& format)
|
||||
{
|
||||
if (format_type == FMT_WRITTEN) {
|
||||
return written_datetime_io->format(when);
|
||||
}
|
||||
else if (format_type == FMT_CUSTOM || format) {
|
||||
datetime_io_map::iterator i = temp_datetime_io.find(*format);
|
||||
if (i != temp_datetime_io.end()) {
|
||||
return (*i).second->format(when);
|
||||
} else {
|
||||
datetime_io_t * formatter = new datetime_io_t(*format, false);
|
||||
temp_datetime_io.insert(datetime_io_map::value_type(*format, formatter));
|
||||
return formatter->format(when);
|
||||
}
|
||||
}
|
||||
else if (format_type == FMT_PRINTED) {
|
||||
return printed_datetime_io->format(when);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string format_date(const date_t& when,
|
||||
const format_type_t format_type,
|
||||
const optional<const char *>& format)
|
||||
{
|
||||
if (format_type == FMT_WRITTEN) {
|
||||
return written_date_io->format(when);
|
||||
}
|
||||
else if (format_type == FMT_CUSTOM || format) {
|
||||
date_io_map::iterator i = temp_date_io.find(*format);
|
||||
if (i != temp_date_io.end()) {
|
||||
return (*i).second->format(when);
|
||||
} else {
|
||||
date_io_t * formatter = new date_io_t(*format, false);
|
||||
temp_date_io.insert(date_io_map::value_type(*format, formatter));
|
||||
return formatter->format(when);
|
||||
}
|
||||
}
|
||||
else if (format_type == FMT_PRINTED) {
|
||||
return printed_date_io->format(when);
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool is_initialized = false;
|
||||
}
|
||||
|
||||
void set_datetime_format(const char * format)
|
||||
{
|
||||
printed_datetime_io->set_format(format);
|
||||
}
|
||||
|
||||
void set_date_format(const char * format)
|
||||
{
|
||||
printed_date_io->set_format(format);
|
||||
}
|
||||
|
||||
void set_input_date_format(const char * format)
|
||||
{
|
||||
input_date_io.reset(new date_io_t(format, true));
|
||||
}
|
||||
|
||||
void times_initialize()
|
||||
{
|
||||
if (! is_initialized) {
|
||||
written_datetime_io.reset(new datetime_io_t("%Y/%m/%d %H:%M:%S", false));
|
||||
written_date_io.reset(new date_io_t("%Y/%m/%d", false));
|
||||
|
||||
printed_datetime_io.reset(new datetime_io_t("%y-%b-%d %H:%M:%S", false));
|
||||
printed_date_io.reset(new date_io_t("%y-%b-%d", false));
|
||||
|
||||
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%m/%d", true)));
|
||||
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m/%d", true)));
|
||||
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%Y/%m", true)));
|
||||
readers.push_back(shared_ptr<date_io_t>(new date_io_t("%y/%m/%d", true)));
|
||||
|
||||
is_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void times_shutdown()
|
||||
{
|
||||
if (is_initialized) {
|
||||
printed_datetime_io.reset();
|
||||
written_datetime_io.reset();
|
||||
input_date_io.reset();
|
||||
printed_date_io.reset();
|
||||
written_date_io.reset();
|
||||
|
||||
readers.clear();
|
||||
|
||||
foreach (datetime_io_map::value_type& pair, temp_datetime_io)
|
||||
checked_delete(pair.second);
|
||||
temp_datetime_io.clear();
|
||||
|
||||
foreach (date_io_map::value_type& pair, temp_date_io)
|
||||
checked_delete(pair.second);
|
||||
temp_date_io.clear();
|
||||
|
||||
is_initialized = false;
|
||||
}
|
||||
}
|
||||
} // namespace ledger
|
||||
|
|
|
|||
41
src/times.h
41
src/times.h
|
|
@ -74,7 +74,6 @@ inline bool is_valid(const date_t& moment) {
|
|||
#define CURRENT_DATE() boost::gregorian::day_clock::universal_day()
|
||||
|
||||
extern date_time::weekdays start_of_week;
|
||||
extern optional<std::string> input_date_format;
|
||||
|
||||
optional<date_time::weekdays>
|
||||
string_to_day_of_week(const std::string& str);
|
||||
|
|
@ -97,33 +96,20 @@ inline date_t parse_date(const std::string& str,
|
|||
return parse_date(str.c_str(), current_year);
|
||||
}
|
||||
|
||||
extern std::string output_datetime_format;
|
||||
enum format_type_t {
|
||||
FMT_WRITTEN, FMT_PRINTED, FMT_CUSTOM
|
||||
};
|
||||
|
||||
inline std::string format_datetime(const datetime_t& when,
|
||||
const optional<std::string>& format = none)
|
||||
{
|
||||
posix_time::time_facet * facet
|
||||
(new posix_time::time_facet(format ? format->c_str() :
|
||||
output_datetime_format.c_str()));
|
||||
std::ostringstream buf;
|
||||
buf.imbue(std::locale(std::locale::classic(), facet));
|
||||
buf << when;
|
||||
return buf.str();
|
||||
}
|
||||
std::string format_datetime(const datetime_t& when,
|
||||
const format_type_t format_type = FMT_PRINTED,
|
||||
const optional<const char *>& format = none);
|
||||
void set_datetime_format(const char * format);
|
||||
|
||||
extern std::string output_date_format;
|
||||
|
||||
inline std::string format_date(const date_t& when,
|
||||
const optional<std::string>& format = none)
|
||||
{
|
||||
gregorian::date_facet * facet
|
||||
(new gregorian::date_facet(format ? format->c_str() :
|
||||
output_date_format.c_str()));
|
||||
std::ostringstream buf;
|
||||
buf.imbue(std::locale(std::locale::classic(), facet));
|
||||
buf << when;
|
||||
return buf.str();
|
||||
}
|
||||
std::string format_date(const date_t& when,
|
||||
const format_type_t format_type = FMT_PRINTED,
|
||||
const optional<const char *>& format = none);
|
||||
void set_date_format(const char * format);
|
||||
void set_input_date_format(const char * format);
|
||||
|
||||
class date_interval_t : public equality_comparable<date_interval_t>
|
||||
{
|
||||
|
|
@ -207,6 +193,9 @@ public:
|
|||
date_interval_t& operator++();
|
||||
};
|
||||
|
||||
void times_initialize();
|
||||
void times_shutdown();
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,
|
||||
const date_interval_t::duration_t& duration);
|
||||
|
||||
|
|
|
|||
17
src/value.cc
17
src/value.cc
|
|
@ -984,7 +984,7 @@ void value_t::in_place_cast(type_t cast_type)
|
|||
set_datetime(datetime_t(as_date(), time_duration(0, 0, 0, 0)));
|
||||
return;
|
||||
case STRING:
|
||||
set_string(format_date(as_date(), string("%Y-%m-%d")));
|
||||
set_string(format_date(as_date(), FMT_WRITTEN));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -996,7 +996,7 @@ void value_t::in_place_cast(type_t cast_type)
|
|||
set_date(as_datetime().date());
|
||||
return;
|
||||
case STRING:
|
||||
set_string(format_datetime(as_datetime(), string("%Y-%m-%d %H:%M:%S")));
|
||||
set_string(format_datetime(as_datetime(), FMT_WRITTEN));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -1495,16 +1495,17 @@ void value_t::print(std::ostream& out,
|
|||
|
||||
case DATETIME:
|
||||
if (date_format)
|
||||
out << format_datetime(as_datetime(), *date_format);
|
||||
out << format_datetime(as_datetime(), FMT_CUSTOM,
|
||||
date_format->c_str());
|
||||
else
|
||||
out << format_datetime(as_datetime());
|
||||
out << format_datetime(as_datetime(), FMT_WRITTEN);
|
||||
break;
|
||||
|
||||
case DATE:
|
||||
if (date_format)
|
||||
out << format_date(as_date(), *date_format);
|
||||
out << format_date(as_date(), FMT_CUSTOM, date_format->c_str());
|
||||
else
|
||||
out << format_date(as_date());
|
||||
out << format_date(as_date(), FMT_WRITTEN);
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
|
|
@ -1579,10 +1580,10 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
|
|||
break;
|
||||
|
||||
case DATETIME:
|
||||
out << '[' << format_datetime(as_datetime()) << ']';
|
||||
out << '[' << format_datetime(as_datetime(), FMT_WRITTEN) << ']';
|
||||
break;
|
||||
case DATE:
|
||||
out << '[' << format_date(as_date()) << ']';
|
||||
out << '[' << format_date(as_date(), FMT_WRITTEN) << ']';
|
||||
break;
|
||||
|
||||
case INTEGER:
|
||||
|
|
|
|||
|
|
@ -934,7 +934,7 @@ public:
|
|||
|
||||
#define NULL_VALUE (value_t())
|
||||
|
||||
inline value_t string_value(const string& str) {
|
||||
inline value_t string_value(const string& str = "") {
|
||||
return value_t(str, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ csv --csv-format='"%(date)"\n'
|
|||
Assets:Investments:Vanguard:VMMXX 0.350 VMMXX @ $1.00
|
||||
Income:Dividends:Vanguard:VMMXX $-0.35
|
||||
>>>1
|
||||
"07-Feb-02"
|
||||
"07-Feb-02"
|
||||
"2007/02/02"
|
||||
"2007/02/02"
|
||||
>>>2
|
||||
=== 0
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ P 2009/02/01 17:30:00 AAPL $50.00
|
|||
Assets:Brokerage 100 AAPL
|
||||
Income
|
||||
>>>1
|
||||
09-Jan-01 13:30:00 $10.00
|
||||
09-Jan-01 14:30:00 $20.00
|
||||
09-Jan-01 15:30:00 $30.00
|
||||
09-Jan-01 16:30:00 $40.00
|
||||
09-Feb-01 17:30:00 $50.00
|
||||
2009/01/01 13:30:00 $10.00
|
||||
2009/01/01 14:30:00 $20.00
|
||||
2009/01/01 15:30:00 $30.00
|
||||
2009/01/01 16:30:00 $40.00
|
||||
2009/02/01 17:30:00 $50.00
|
||||
>>>2
|
||||
=== 0
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ P 2009/02/01 17:30:00 AAPL $50.00
|
|||
Assets:Brokerage 100 AAPL
|
||||
Income
|
||||
>>>1
|
||||
P 09-Jan-01 $10.00
|
||||
P 09-Jan-01 $20.00
|
||||
P 09-Jan-01 $30.00
|
||||
P 09-Jan-01 $40.00
|
||||
P 09-Feb-01 $50.00
|
||||
P 2009/01/01 $10.00
|
||||
P 2009/01/01 $20.00
|
||||
P 2009/01/01 $30.00
|
||||
P 2009/01/01 $40.00
|
||||
P 2009/02/01 $50.00
|
||||
>>>2
|
||||
=== 0
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ period june 2008
|
|||
>>>1
|
||||
global details =>
|
||||
|
||||
start: 2008-06-01
|
||||
end: 2008-07-01
|
||||
start: 08-Jun-01
|
||||
end: 08-Jul-01
|
||||
factor: 1
|
||||
>>>2
|
||||
=== 0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue