mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Replace GDateTime dependency with boost::date_time.
This commit is contained in:
parent
6673128b9f
commit
6c6153b5b6
@ -23,10 +23,15 @@
|
|||||||
|
|
||||||
#ifndef __GNC_DATE_P_H__
|
#ifndef __GNC_DATE_P_H__
|
||||||
#define __GNC_DATE_P_H__
|
#define __GNC_DATE_P_H__
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include "gnc-date.h"
|
#include "gnc-date.h"
|
||||||
|
|
||||||
#define NANOS_PER_SECOND 1000000000
|
#define NANOS_PER_SECOND INT32_C(1000000000)
|
||||||
|
|
||||||
/** Convert a given date/time format from UTF-8 to an encoding suitable for the
|
/** Convert a given date/time format from UTF-8 to an encoding suitable for the
|
||||||
* strftime system call.
|
* strftime system call.
|
||||||
@ -74,4 +79,7 @@ typedef struct
|
|||||||
|
|
||||||
Testfuncs *gnc_date_load_funcs (void);
|
Testfuncs *gnc_date_load_funcs (void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif /* __GNC_DATE_P_H__ */
|
#endif /* __GNC_DATE_P_H__ */
|
||||||
|
@ -25,46 +25,36 @@
|
|||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
#define __EXTENSIONS__
|
#define __EXTENSIONS__
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <glib/gprintf.h>
|
#include <libintl.h>
|
||||||
/* to be renamed qofdate.c */
|
#include "platform.h"
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_LANGINFO_D_FMT
|
|
||||||
# include <langinfo.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
|
||||||
#include <glib/gi18n.h>
|
|
||||||
|
|
||||||
#include "gnc-date-p.h"
|
|
||||||
#include "qof.h"
|
#include "qof.h"
|
||||||
|
|
||||||
#ifndef HAVE_STRPTIME
|
#ifdef HAVE_LANGINFO_D_FMT
|
||||||
#include "strptime.h"
|
# include <langinfo.h>
|
||||||
#endif
|
#endif
|
||||||
#ifndef HAVE_LOCALTIME_R
|
|
||||||
#include "localtime_r.h"
|
|
||||||
#endif
|
|
||||||
#include "platform.h"
|
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
#include "gnc-date.h"
|
||||||
|
#include "gnc-date-p.h"
|
||||||
|
|
||||||
|
#include "gnc-timezone.hpp"
|
||||||
|
#define N_(string) string //So that xgettext will find it
|
||||||
|
|
||||||
|
using Date = boost::gregorian::date;
|
||||||
|
using Month = boost::gregorian::greg_month;
|
||||||
|
using PTime = boost::posix_time::ptime;
|
||||||
|
using LDT = boost::local_time::local_date_time;
|
||||||
|
using Duration = boost::posix_time::time_duration;
|
||||||
|
using LDTBase = boost::local_time::local_date_time_base<PTime, boost::date_time::time_zone_base<PTime, char>>;
|
||||||
|
|
||||||
#ifdef HAVE_LANGINFO_D_FMT
|
#ifdef HAVE_LANGINFO_D_FMT
|
||||||
# define GNC_D_FMT (nl_langinfo (D_FMT))
|
# define GNC_D_FMT (nl_langinfo (D_FMT))
|
||||||
@ -101,151 +91,55 @@ static int dateCompletionBackMonths = 6;
|
|||||||
/* This static indicates the debugging module that this .o belongs to. */
|
/* This static indicates the debugging module that this .o belongs to. */
|
||||||
static QofLogModule log_module = QOF_MOD_ENGINE;
|
static QofLogModule log_module = QOF_MOD_ENGINE;
|
||||||
|
|
||||||
/* Getting a timezone is expensive, and we do it a lot. Cache the value. */
|
// Default constructor Initializes to the current locale.
|
||||||
static GTimeZone*
|
static const TimeZoneProvider tzp;
|
||||||
gnc_g_time_zone_new_local (void)
|
// For converting to/from POSIX time.
|
||||||
{
|
static const PTime unix_epoch (Date(1970, boost::gregorian::Jan, 1),
|
||||||
static GTimeZone* tz = NULL;
|
boost::posix_time::seconds(0));
|
||||||
if (tz)
|
/* To ensure things aren't overly screwed up by setting the nanosecond clock for boost::date_time. Don't do it, though, it doesn't get us anything and slows down the date/time library. */
|
||||||
return tz;
|
#ifndef BOOST_DATE_TIME_HAS_NANOSECONDS
|
||||||
tz = g_time_zone_new_local();
|
static constexpr uint64_t ticks_per_second = UINT64_C(1000000);
|
||||||
return tz;
|
#else
|
||||||
}
|
static constexpr uint64_t ticks_per_second = UINT64_C(1000000000);
|
||||||
|
|
||||||
static GDateTime*
|
|
||||||
gnc_g_date_time_new_local (gint year, gint month, gint day, gint hour, gint minute, gdouble seconds)
|
|
||||||
{
|
|
||||||
GTimeZone *tz = gnc_g_time_zone_new_local();
|
|
||||||
GDateTime *gdt = g_date_time_new (tz, year, month, day,
|
|
||||||
hour, minute, seconds);
|
|
||||||
if (!gdt)
|
|
||||||
return gdt;
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
/* g_date_time_new truncates nanoseconds to microseconds. Sometimes in
|
|
||||||
* converting (particularly when parsing from a string) the
|
|
||||||
* nanoseconds will have lost 1/2 a femtosecond or so. Adding 1/2 a
|
|
||||||
* nano second ensures that the truncation doesn't lose a micorsecond
|
|
||||||
* in translation.
|
|
||||||
*/
|
|
||||||
seconds += 5e-10;
|
|
||||||
gdt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
|
|
||||||
return gdt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GDateTime*
|
|
||||||
gnc_g_date_time_adjust_for_dst (GDateTime *gdt, GTimeZone *tz)
|
|
||||||
{
|
|
||||||
GDateTime *ngdt;
|
|
||||||
g_return_val_if_fail (gdt != NULL, NULL);
|
|
||||||
ngdt = g_date_time_to_timezone (gdt, tz);
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
gdt = g_date_time_to_timezone (ngdt, tz);
|
|
||||||
g_date_time_unref (ngdt);
|
|
||||||
return gdt;
|
|
||||||
}
|
|
||||||
|
|
||||||
GDateTime*
|
|
||||||
gnc_g_date_time_new_from_unix_local (time64 time)
|
|
||||||
{
|
|
||||||
GTimeZone *tz = gnc_g_time_zone_new_local ();
|
|
||||||
GDateTime *gdt = g_date_time_new_from_unix_utc (time);
|
|
||||||
if (gdt)
|
|
||||||
gdt = gnc_g_date_time_adjust_for_dst (gdt, tz);
|
|
||||||
return gdt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GDateTime*
|
|
||||||
gnc_g_date_time_new_from_timeval_local (const GTimeVal* tv)
|
|
||||||
{
|
|
||||||
GTimeZone *tz = gnc_g_time_zone_new_local ();
|
|
||||||
GDateTime *gdt = g_date_time_new_from_timeval_utc (tv);
|
|
||||||
if (gdt)
|
|
||||||
gdt = gnc_g_date_time_adjust_for_dst (gdt, tz);
|
|
||||||
return gdt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GDateTime*
|
|
||||||
gnc_g_date_time_new_now_local (void)
|
|
||||||
{
|
|
||||||
GTimeZone *tz = gnc_g_time_zone_new_local ();
|
|
||||||
GDateTime *gdt = g_date_time_new_now_utc ();
|
|
||||||
if (gdt)
|
|
||||||
gdt = gnc_g_date_time_adjust_for_dst (gdt, tz);
|
|
||||||
return gdt;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static GDateTime*
|
|
||||||
gnc_g_date_time_to_local (GDateTime* gdt)
|
|
||||||
{
|
|
||||||
GTimeZone *tz = NULL;
|
|
||||||
if (gdt)
|
|
||||||
{
|
|
||||||
tz = gnc_g_time_zone_new_local ();
|
|
||||||
gdt = gnc_g_date_time_adjust_for_dst (g_date_time_to_utc (gdt), tz);
|
|
||||||
}
|
|
||||||
return gdt;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GDateTime *(*new_local)(gint, gint, gint, gint, gint, gdouble);
|
|
||||||
GDateTime *(*adjust_for_dst)(GDateTime *, GTimeZone *);
|
|
||||||
GDateTime *(*new_from_unix_local)(time64);
|
|
||||||
GDateTime *(*new_from_timeval_local)(const GTimeVal *);
|
|
||||||
GDateTime *(*new_now_local)(void);
|
|
||||||
GDateTime *(*to_local)(GDateTime *);
|
|
||||||
} _GncDateTime;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
static LDT
|
||||||
void _gnc_date_time_init(_GncDateTime*);
|
gnc_get_LDT(int year, int month, int day, int hour, int minute, int seconds)
|
||||||
void
|
|
||||||
_gnc_date_time_init (_GncDateTime *gncdt)
|
|
||||||
{
|
{
|
||||||
gncdt->new_local = gnc_g_date_time_new_local;
|
Date date(year, static_cast<Month>(month), day);
|
||||||
gncdt->adjust_for_dst = gnc_g_date_time_adjust_for_dst;
|
Duration time(hour, minute, seconds);
|
||||||
gncdt->new_from_unix_local = gnc_g_date_time_new_from_unix_local;
|
auto tz = tzp.get(year);
|
||||||
gncdt->new_from_timeval_local = gnc_g_date_time_new_from_timeval_local;
|
return LDT(date, time, tz, LDTBase::NOT_DATE_TIME_ON_ERROR);
|
||||||
gncdt->new_now_local = gnc_g_date_time_new_now_local;
|
|
||||||
gncdt->to_local = gnc_g_date_time_to_local;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
static LDT
|
||||||
|
LDT_from_unix_local(const time64 time)
|
||||||
|
{
|
||||||
|
PTime temp(unix_epoch.date(),
|
||||||
|
boost::posix_time::hours(time / 3600) +
|
||||||
|
boost::posix_time::seconds(time % 3600));
|
||||||
|
auto tz = tzp.get(temp.date().year());
|
||||||
|
return LDT(temp, tz);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static time64
|
||||||
|
time64_from_date_time(T time)
|
||||||
|
{
|
||||||
|
auto duration = time - unix_epoch;
|
||||||
|
return duration.ticks() / ticks_per_second;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************** Posix Replacement Functions ***************************/
|
/****************** Posix Replacement Functions ***************************/
|
||||||
void
|
void
|
||||||
gnc_tm_free (struct tm* time)
|
gnc_tm_free (struct tm* time)
|
||||||
{
|
{
|
||||||
g_slice_free1 (sizeof (struct tm), time);
|
free(time);
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_TZ_SIZE
|
|
||||||
static void
|
|
||||||
gnc_g_date_time_fill_struct_tm (GDateTime *gdt, struct tm* time)
|
|
||||||
{
|
|
||||||
memset (time, 0, sizeof (struct tm));
|
|
||||||
g_date_time_get_ymd (gdt, &(time->tm_year), &(time->tm_mon), &(time->tm_mday));
|
|
||||||
time->tm_sec = g_date_time_get_second (gdt);
|
|
||||||
time->tm_min = g_date_time_get_minute (gdt);
|
|
||||||
time->tm_hour = g_date_time_get_hour (gdt);
|
|
||||||
// Watch out: struct tm has wday=0..6 with Sunday=0, but GDateTime has wday=1..7 with Sunday=7.
|
|
||||||
time->tm_wday = g_date_time_get_day_of_week (gdt) % 7;
|
|
||||||
time->tm_yday = g_date_time_get_day_of_year (gdt);
|
|
||||||
time->tm_isdst = g_date_time_is_daylight_savings (gdt);
|
|
||||||
time->tm_year -= 1900;
|
|
||||||
--time->tm_mon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm*
|
struct tm*
|
||||||
gnc_localtime (const time64 *secs)
|
gnc_localtime (const time64 *secs)
|
||||||
{
|
{
|
||||||
struct tm *time = static_cast<struct tm*>(g_slice_alloc0 (sizeof (struct tm)));
|
auto time = static_cast<struct tm*>(calloc(1, sizeof(struct tm)));
|
||||||
if (gnc_localtime_r (secs, time) == NULL)
|
if (gnc_localtime_r (secs, time) == NULL)
|
||||||
{
|
{
|
||||||
gnc_tm_free (time);
|
gnc_tm_free (time);
|
||||||
@ -254,39 +148,41 @@ gnc_localtime (const time64 *secs)
|
|||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Linux, Darwin, and MSWindows implementations of this function set the
|
|
||||||
* globals timezone and daylight; BSD doesn't have those globals, and
|
|
||||||
* Gnucash never uses them, so they're omitted from this
|
|
||||||
* implementation. Bug 704185.
|
|
||||||
*/
|
|
||||||
struct tm*
|
struct tm*
|
||||||
gnc_localtime_r (const time64 *secs, struct tm* time)
|
gnc_localtime_r (const time64 *secs, struct tm* time)
|
||||||
{
|
{
|
||||||
GDateTime *gdt = gnc_g_date_time_new_from_unix_local (*secs);
|
try
|
||||||
g_return_val_if_fail (gdt != NULL, NULL);
|
{
|
||||||
|
auto ldt = LDT_from_unix_local(*secs);
|
||||||
gnc_g_date_time_fill_struct_tm (gdt, time);
|
*time = boost::local_time::to_tm(ldt);
|
||||||
if (g_date_time_is_daylight_savings (gdt))
|
|
||||||
time->tm_isdst = 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_TM_GMTOFF
|
#ifdef HAVE_STRUCT_TM_GMTOFF
|
||||||
time->tm_gmtoff = g_date_time_get_utc_offset (gdt) / G_TIME_SPAN_SECOND;
|
auto offset = ldt.zone()->base_utc_offset();
|
||||||
|
if (ldt.is_dst())
|
||||||
|
offset += ldt.zone()->dst_offset();
|
||||||
|
time->tm_gmtoff = offset.total_seconds();
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
g_date_time_unref (gdt);
|
catch(boost::gregorian::bad_year)
|
||||||
return time;
|
{
|
||||||
|
return NULL; //Yeah, it should be nullptr, but this is a C-linkage func.
|
||||||
|
}
|
||||||
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tm*
|
struct tm*
|
||||||
gnc_gmtime (const time64 *secs)
|
gnc_gmtime (const time64 *secs)
|
||||||
{
|
{
|
||||||
struct tm *time;
|
auto time = static_cast<struct tm*>(calloc(1, sizeof (struct tm)));
|
||||||
GDateTime *gdt = g_date_time_new_from_unix_utc (*secs);
|
try {
|
||||||
g_return_val_if_fail (gdt != NULL, NULL);
|
PTime pdt(unix_epoch.date(), boost::posix_time::hours(*secs / 3600) +
|
||||||
time = static_cast<struct tm*>(g_slice_alloc0 (sizeof (struct tm)));
|
boost::posix_time::seconds(*secs % 3600));
|
||||||
gnc_g_date_time_fill_struct_tm (gdt, time);
|
*time = boost::posix_time::to_tm(pdt);
|
||||||
g_date_time_unref (gdt);
|
}
|
||||||
return time;
|
catch(boost::gregorian::bad_year)
|
||||||
|
{
|
||||||
|
return NULL; //Yeah, it should be nullptr, but this is a C-linkage func.
|
||||||
|
}
|
||||||
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -318,10 +214,10 @@ normalize_struct_tm (struct tm* time)
|
|||||||
gint last_day;
|
gint last_day;
|
||||||
|
|
||||||
++time->tm_mon;
|
++time->tm_mon;
|
||||||
/* GDateTime doesn't protect itself against out-of range years,
|
/* Gregorian_date throws if it gets an out-of-range year
|
||||||
* so clamp year into GDateTime's range.
|
* so clamp year into gregorian_date's range.
|
||||||
*/
|
*/
|
||||||
if (year < 0) year = -year;
|
if (year < 1400) year += 1400;
|
||||||
if (year > 9999) year %= 10000;
|
if (year > 9999) year %= 10000;
|
||||||
|
|
||||||
normalize_time_component (&(time->tm_sec), &(time->tm_min), 60, 0);
|
normalize_time_component (&(time->tm_sec), &(time->tm_min), 60, 0);
|
||||||
@ -348,68 +244,30 @@ normalize_struct_tm (struct tm* time)
|
|||||||
time64
|
time64
|
||||||
gnc_mktime (struct tm* time)
|
gnc_mktime (struct tm* time)
|
||||||
{
|
{
|
||||||
GDateTime *gdt;
|
normalize_struct_tm (time);
|
||||||
time64 secs;
|
return time64_from_date_time(boost::posix_time::ptime_from_tm(*time));
|
||||||
normalize_struct_tm (time);
|
|
||||||
gdt = gnc_g_date_time_new_local (time->tm_year + 1900, time->tm_mon,
|
|
||||||
time->tm_mday, time->tm_hour,
|
|
||||||
time->tm_min, (gdouble)(time->tm_sec));
|
|
||||||
if (gdt == NULL)
|
|
||||||
{
|
|
||||||
g_warning("Invalid time passed to gnc_mktime");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
time->tm_mon = time->tm_mon > 0 ? time->tm_mon - 1 : 11;
|
|
||||||
// Watch out: struct tm has wday=0..6 with Sunday=0, but GDateTime has wday=1..7 with Sunday=7.
|
|
||||||
time->tm_wday = g_date_time_get_day_of_week (gdt) % 7;
|
|
||||||
time->tm_yday = g_date_time_get_day_of_year (gdt);
|
|
||||||
time->tm_isdst = g_date_time_is_daylight_savings (gdt);
|
|
||||||
|
|
||||||
#ifdef HAVE_STRUCT_TM_GMTOFF
|
|
||||||
time->tm_gmtoff = g_date_time_get_utc_offset (gdt) / G_TIME_SPAN_SECOND;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
secs = g_date_time_to_unix (gdt);
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
return secs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time64
|
time64
|
||||||
gnc_timegm (struct tm* time)
|
gnc_timegm (struct tm* time)
|
||||||
{
|
{
|
||||||
GDateTime *gdt;
|
auto newtime = *time;
|
||||||
time64 secs;
|
newtime.tm_gmtoff = 0;
|
||||||
normalize_struct_tm (time);
|
return gnc_mktime(&newtime);
|
||||||
gdt = g_date_time_new_utc (time->tm_year + 1900, time->tm_mon,
|
|
||||||
time->tm_mday, time->tm_hour, time->tm_min,
|
|
||||||
(gdouble)(time->tm_sec));
|
|
||||||
time->tm_mon = time->tm_mon > 0 ? time->tm_mon - 1 : 11;
|
|
||||||
// Watch out: struct tm has wday=0..6 with Sunday=0, but GDateTime has wday=1..7 with Sunday=7.
|
|
||||||
time->tm_wday = g_date_time_get_day_of_week (gdt) % 7;
|
|
||||||
time->tm_yday = g_date_time_get_day_of_year (gdt);
|
|
||||||
time->tm_isdst = g_date_time_is_daylight_savings (gdt);
|
|
||||||
|
|
||||||
secs = g_date_time_to_unix (gdt);
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
return secs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar*
|
char*
|
||||||
gnc_ctime (const time64 *secs)
|
gnc_ctime (const time64 *secs)
|
||||||
{
|
{
|
||||||
GDateTime *gdt = gnc_g_date_time_new_from_unix_local (*secs);
|
return gnc_print_time64(*secs, "%a %b %e %H:%M:%S %Y");
|
||||||
gchar *string = g_date_time_format (gdt, "%a %b %e %H:%M:%S %Y");
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
return string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time64
|
time64
|
||||||
gnc_time (time64 *tbuf)
|
gnc_time (time64 *tbuf)
|
||||||
{
|
{
|
||||||
GDateTime *gdt = gnc_g_date_time_new_now_local ();
|
auto pdt = boost::posix_time::second_clock::local_time();
|
||||||
time64 secs = g_date_time_to_unix (gdt);
|
auto secs = time64_from_date_time(pdt);
|
||||||
g_date_time_unref (gdt);
|
if (tbuf != nullptr)
|
||||||
if (tbuf != NULL)
|
|
||||||
*tbuf = secs;
|
*tbuf = secs;
|
||||||
return secs;
|
return secs;
|
||||||
}
|
}
|
||||||
@ -417,9 +275,8 @@ gnc_time (time64 *tbuf)
|
|||||||
time64
|
time64
|
||||||
gnc_time_utc (time64 *tbuf)
|
gnc_time_utc (time64 *tbuf)
|
||||||
{
|
{
|
||||||
GDateTime *gdt = g_date_time_new_now_utc ();
|
auto pdt = boost::posix_time::second_clock::universal_time();
|
||||||
time64 secs = g_date_time_to_unix (gdt);
|
auto secs = time64_from_date_time(pdt);
|
||||||
g_date_time_unref (gdt);
|
|
||||||
if (tbuf != NULL)
|
if (tbuf != NULL)
|
||||||
*tbuf = secs;
|
*tbuf = secs;
|
||||||
return secs;
|
return secs;
|
||||||
@ -434,17 +291,6 @@ gnc_difftime (const time64 secs1, const time64 secs2)
|
|||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
GDateTime*
|
|
||||||
gnc_g_date_time_new_from_timespec_local (Timespec ts)
|
|
||||||
{
|
|
||||||
GDateTime *gdt1 = gnc_g_date_time_new_from_unix_local (ts.tv_sec);
|
|
||||||
double nsecs = ((double)ts.tv_nsec + 0.5)/ 1000000000.0L;
|
|
||||||
GDateTime *gdt2 = g_date_time_add_seconds (gdt1, nsecs);
|
|
||||||
g_date_time_unref (gdt1);
|
|
||||||
g_assert (g_date_time_to_unix (gdt2) == ts.tv_sec + (nsecs >= 1.0 ? (gint64)nsecs : 0));
|
|
||||||
return gdt2;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
gnc_date_dateformat_to_string(QofDateFormat format)
|
gnc_date_dateformat_to_string(QofDateFormat format)
|
||||||
{
|
{
|
||||||
@ -530,6 +376,24 @@ gnc_date_string_to_monthformat(const char *fmt_str, GNCDateMonthFormat *format)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
gnc_print_time64(time64 time, const char* format)
|
||||||
|
{
|
||||||
|
using Facet = boost::local_time::local_time_facet;
|
||||||
|
auto date_time = LDT_from_unix_local(time);
|
||||||
|
std::stringstream ss;
|
||||||
|
//The stream destructor frees the facet, so it must be heap-allocated.
|
||||||
|
auto output_facet(new Facet(format));
|
||||||
|
ss.imbue(std::locale(std::locale(), output_facet));
|
||||||
|
ss << date_time;
|
||||||
|
auto sstr = ss.str();
|
||||||
|
//ugly C allocation so that the ptr can be freed at the other end
|
||||||
|
char* cstr = static_cast<char*>(malloc(sstr.length() + 1));
|
||||||
|
memset(cstr, 0, sstr.length() + 1);
|
||||||
|
strncpy(cstr, sstr.c_str(), sstr.length());
|
||||||
|
return cstr;
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
@ -1412,10 +1276,7 @@ qof_strftime(gchar *buf, gsize max, const gchar *format, const struct tm *tm)
|
|||||||
gchar *
|
gchar *
|
||||||
gnc_date_timestamp (void)
|
gnc_date_timestamp (void)
|
||||||
{
|
{
|
||||||
GDateTime *gdt = gnc_g_date_time_new_now_local ();
|
return gnc_print_time64(gnc_time(nullptr), "%Y-%M-%d %H:%M%S");
|
||||||
gchar *timestr = g_date_time_format (gdt, "%Y%m%d%H%M%S");
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
return timestr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@ -1429,38 +1290,9 @@ gnc_date_timestamp (void)
|
|||||||
Timespec
|
Timespec
|
||||||
gnc_iso8601_to_timespec_gmt(const char *str)
|
gnc_iso8601_to_timespec_gmt(const char *str)
|
||||||
{
|
{
|
||||||
Timespec time = { 0L, 0L };
|
auto pdt = boost::posix_time::time_from_string(str);
|
||||||
GDateTime *gdt;
|
auto time = time64_from_date_time(pdt);
|
||||||
gint hour = 0, minute = 0, day = 0, month = 0, year = 0;
|
return {time, 0};
|
||||||
gchar zone[12];
|
|
||||||
gdouble second = 0.0;
|
|
||||||
gint fields;
|
|
||||||
|
|
||||||
memset (zone, 0, sizeof (zone));
|
|
||||||
|
|
||||||
if (!str)
|
|
||||||
return time;
|
|
||||||
|
|
||||||
fields = sscanf (str, ISO_DATE_FORMAT, &year, &month,
|
|
||||||
&day, &hour, &minute, &second, zone);
|
|
||||||
if (fields < 1)
|
|
||||||
return time;
|
|
||||||
else if (fields > 6 && strlen (zone) > 0) /* Date string included a timezone */
|
|
||||||
{
|
|
||||||
GTimeZone *tz = g_time_zone_new (zone);
|
|
||||||
second += 5e-10;
|
|
||||||
gdt = g_date_time_new (tz, year, month, day, hour, minute, second);
|
|
||||||
}
|
|
||||||
else /* No zone info, assume UTC */
|
|
||||||
{
|
|
||||||
second += 5e-10;
|
|
||||||
gdt = g_date_time_new_utc (year, month, day, hour, minute, second);
|
|
||||||
}
|
|
||||||
|
|
||||||
time.tv_sec = g_date_time_to_unix (gdt);
|
|
||||||
time.tv_nsec = g_date_time_get_microsecond (gdt) * 1000;
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@ -1469,28 +1301,20 @@ gnc_iso8601_to_timespec_gmt(const char *str)
|
|||||||
char *
|
char *
|
||||||
gnc_timespec_to_iso8601_buff (Timespec ts, char * buff)
|
gnc_timespec_to_iso8601_buff (Timespec ts, char * buff)
|
||||||
{
|
{
|
||||||
const gchar *fmt1 = "%Y-%m-%d %H:%M", *fmt2 = "%s:%02d.%06d %s";
|
constexpr size_t max_iso_date_length = 32;
|
||||||
GDateTime *gdt;
|
std::string fmt1 = "%Y-%m-%d %H:%M";
|
||||||
gchar *time_base, *tz;
|
|
||||||
|
|
||||||
g_return_val_if_fail (buff != NULL, NULL);
|
g_return_val_if_fail (buff != NULL, NULL);
|
||||||
gdt = gnc_g_date_time_new_from_timespec_local (ts);
|
|
||||||
g_return_val_if_fail (gdt != NULL, NULL);
|
|
||||||
time_base = g_date_time_format (gdt, fmt1);
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
tz = g_date_time_format (gdt, "%Z");
|
fmt1 += "%Z";
|
||||||
#else
|
#else
|
||||||
tz = g_date_time_format (gdt, "%z");
|
fmt1 += "%z";
|
||||||
#endif
|
#endif
|
||||||
snprintf (buff, MAX_DATE_LENGTH, fmt2, time_base,
|
char* str = gnc_print_time64(ts.tv_sec, fmt1.c_str());
|
||||||
g_date_time_get_second (gdt), g_date_time_get_microsecond (gdt),
|
strncpy (buff, str, max_iso_date_length);
|
||||||
tz);
|
free(str);
|
||||||
|
|
||||||
g_free (time_base);
|
|
||||||
g_free (tz);
|
|
||||||
g_date_time_unref (gdt);
|
|
||||||
return buff + strlen (buff);
|
return buff + strlen (buff);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1614,16 +1438,13 @@ GDate timespec_to_gdate (Timespec ts)
|
|||||||
|
|
||||||
GDate* gnc_g_date_new_today ()
|
GDate* gnc_g_date_new_today ()
|
||||||
{
|
{
|
||||||
GDateTime *gdt = gnc_g_date_time_new_now_local ();
|
|
||||||
gint day, month, year;
|
|
||||||
GDate *result;
|
|
||||||
|
|
||||||
g_date_time_get_ymd (gdt, &year, &month, &day);
|
auto pdt = boost::posix_time::second_clock::local_time();
|
||||||
result = g_date_new_dmy (day, static_cast<GDateMonth>(month), year);
|
auto ymd = pdt.date().year_month_day();
|
||||||
g_date_time_unref (gdt);
|
auto month = static_cast<GDateMonth>(ymd.month.as_number());
|
||||||
g_assert(g_date_valid (result));
|
auto result = g_date_new_dmy (ymd.day, month, ymd.year);
|
||||||
|
g_assert(g_date_valid (result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timespec gdate_to_timespec (GDate d)
|
Timespec gdate_to_timespec (GDate d)
|
||||||
|
@ -238,12 +238,6 @@ time64 gnc_time_utc (time64 *tbuf);
|
|||||||
*/
|
*/
|
||||||
gdouble gnc_difftime (const time64 secs1, const time64 secs2);
|
gdouble gnc_difftime (const time64 secs1, const time64 secs2);
|
||||||
|
|
||||||
/** Wrapper for g_date_time_new_from_unix_local() that takes special care on
|
|
||||||
* windows to take the local timezone into account. On unix, it just calles the
|
|
||||||
* g_date function. */
|
|
||||||
GDateTime*
|
|
||||||
gnc_g_date_time_new_from_unix_local (time64 time);
|
|
||||||
|
|
||||||
/** \brief free a struct tm* created with gnc_localtime() or gnc_gmtime()
|
/** \brief free a struct tm* created with gnc_localtime() or gnc_gmtime()
|
||||||
* \param time: The struct tm* to be freed.
|
* \param time: The struct tm* to be freed.
|
||||||
*/
|
*/
|
||||||
@ -280,6 +274,19 @@ Note the reversed return values!
|
|||||||
*/
|
*/
|
||||||
gboolean gnc_date_string_to_monthformat(const gchar *format_string,
|
gboolean gnc_date_string_to_monthformat(const gchar *format_string,
|
||||||
GNCDateMonthFormat *format);
|
GNCDateMonthFormat *format);
|
||||||
|
|
||||||
|
/** \brief print a time64 as a date string per format
|
||||||
|
* \param time
|
||||||
|
* \param format A date format conforming to the strftime format rules.
|
||||||
|
* \return a raw heap-allocated char* which must be freed.
|
||||||
|
*/
|
||||||
|
char* gnc_print_time64(time64 time, const char* format);
|
||||||
|
|
||||||
|
/** Returns a newly allocated date of the current clock time, taken from
|
||||||
|
* time(2). The caller must g_date_free() the object afterwards. */
|
||||||
|
GDate* gnc_g_date_new_today (void);
|
||||||
|
|
||||||
|
|
||||||
// @}
|
// @}
|
||||||
|
|
||||||
/* Datatypes *******************************************************/
|
/* Datatypes *******************************************************/
|
||||||
@ -338,10 +345,6 @@ void timespecFromTime64 (Timespec *ts, time64 t );
|
|||||||
/** Turns a Timespec into a time64 */
|
/** Turns a Timespec into a time64 */
|
||||||
time64 timespecToTime64 (Timespec ts);
|
time64 timespecToTime64 (Timespec ts);
|
||||||
|
|
||||||
/** Returns a newly allocated date of the current clock time, taken from
|
|
||||||
* time(2). The caller must g_date_free() the object afterwards. */
|
|
||||||
GDate* gnc_g_date_new_today (void);
|
|
||||||
|
|
||||||
/** Turns a Timespec into a GDate */
|
/** Turns a Timespec into a GDate */
|
||||||
GDate timespec_to_gdate (Timespec ts);
|
GDate timespec_to_gdate (Timespec ts);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user