mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
Use a 64-bit 'timestamp_t' for all timestamps, rather than 'time_t'
This makes the time type unambiguous, and we can use G_TYPE_INT64 for it in the divelist too. It also implements a portable (and thread-safe) "utc_mkdate()" function that acts kind of like gmtime_r(), but using the 64-bit timestamp_t. It matches our original "utc_mktime()". Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
d14932058f
commit
dce08deb34
10 changed files with 195 additions and 114 deletions
5
Makefile
5
Makefile
|
@ -118,7 +118,7 @@ endif
|
||||||
|
|
||||||
LIBS = $(LIBXML2) $(LIBXSLT) $(LIBGTK) $(LIBGCONF2) $(LIBDIVECOMPUTER) $(EXTRALIBS) $(LIBZIP) -lpthread -lm
|
LIBS = $(LIBXML2) $(LIBXSLT) $(LIBGTK) $(LIBGCONF2) $(LIBDIVECOMPUTER) $(EXTRALIBS) $(LIBZIP) -lpthread -lm
|
||||||
|
|
||||||
OBJS = main.o dive.o profile.o info.o equipment.o divelist.o \
|
OBJS = main.o dive.o time.o profile.o info.o equipment.o divelist.o \
|
||||||
parse-xml.o save-xml.o libdivecomputer.o print.o uemis.o \
|
parse-xml.o save-xml.o libdivecomputer.o print.o uemis.o \
|
||||||
gtk-gui.o statistics.o file.o cochran.o $(OSSUPPORT).o $(RESFILE)
|
gtk-gui.o statistics.o file.o cochran.o $(OSSUPPORT).o $(RESFILE)
|
||||||
|
|
||||||
|
@ -167,6 +167,9 @@ save-xml.o: save-xml.c dive.h
|
||||||
dive.o: dive.c dive.h
|
dive.o: dive.c dive.h
|
||||||
$(CC) $(CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c dive.c
|
$(CC) $(CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c dive.c
|
||||||
|
|
||||||
|
time.o: time.c dive.h
|
||||||
|
$(CC) $(CFLAGS) $(GLIB2CFLAGS) $(XML2CFLAGS) -c time.c
|
||||||
|
|
||||||
main.o: main.c dive.h display.h divelist.h
|
main.o: main.c dive.h display.h divelist.h
|
||||||
$(CC) $(CFLAGS) $(GLIB2CFLAGS) $(GCONF2CFLAGS) $(XML2CFLAGS) -c main.c
|
$(CC) $(CFLAGS) $(GLIB2CFLAGS) $(GCONF2CFLAGS) $(XML2CFLAGS) -c main.c
|
||||||
|
|
||||||
|
|
13
dive.h
13
dive.h
|
@ -236,6 +236,7 @@ struct event {
|
||||||
#define W_IDX_PRIMARY 0
|
#define W_IDX_PRIMARY 0
|
||||||
#define W_IDX_SECONDARY 1
|
#define W_IDX_SECONDARY 1
|
||||||
|
|
||||||
|
typedef gint64 timestamp_t;
|
||||||
typedef enum { TF_NONE, NO_TRIP, IN_TRIP, NUM_TRIPFLAGS } tripflag_t;
|
typedef enum { TF_NONE, NO_TRIP, IN_TRIP, NUM_TRIPFLAGS } tripflag_t;
|
||||||
extern const char *tripflag_names[NUM_TRIPFLAGS];
|
extern const char *tripflag_names[NUM_TRIPFLAGS];
|
||||||
|
|
||||||
|
@ -244,7 +245,7 @@ struct dive {
|
||||||
tripflag_t tripflag;
|
tripflag_t tripflag;
|
||||||
struct dive *divetrip;
|
struct dive *divetrip;
|
||||||
int selected;
|
int selected;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
char *location;
|
char *location;
|
||||||
char *notes;
|
char *notes;
|
||||||
char *divemaster, *buddy;
|
char *divemaster, *buddy;
|
||||||
|
@ -289,7 +290,7 @@ static inline int dive_date_cmp(gconstpointer _a, gconstpointer _b) {
|
||||||
|
|
||||||
/* returns 0 if the dive happened exactly at time */
|
/* returns 0 if the dive happened exactly at time */
|
||||||
static inline int dive_when_find(gconstpointer _dive, gconstpointer _time) {
|
static inline int dive_when_find(gconstpointer _dive, gconstpointer _time) {
|
||||||
return ((struct dive *)_dive)->when != (time_t) _time;
|
return ((struct dive *)_dive)->when != (timestamp_t) _time;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FIND_TRIP(_when) g_list_find_custom(dive_trip_list, (gconstpointer)(_when), dive_when_find)
|
#define FIND_TRIP(_when) g_list_find_custom(dive_trip_list, (gconstpointer)(_when), dive_when_find)
|
||||||
|
@ -300,9 +301,10 @@ static void dump_trip_list(void)
|
||||||
GList *p = NULL;
|
GList *p = NULL;
|
||||||
int i=0;
|
int i=0;
|
||||||
while ((p = NEXT_TRIP(p))) {
|
while ((p = NEXT_TRIP(p))) {
|
||||||
struct tm *tm = gmtime(&DIVE_TRIP(p)->when);
|
struct tm tm;
|
||||||
|
utc_mkdate(DIVE_TRIP(p)->when, &tm);
|
||||||
printf("trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u\n", ++i, DIVE_TRIP(p)->location,
|
printf("trip %d to \"%s\" on %04u-%02u-%02u %02u:%02u:%02u\n", ++i, DIVE_TRIP(p)->location,
|
||||||
tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
tm.tm_year + 1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||||
}
|
}
|
||||||
printf("-----\n");
|
printf("-----\n");
|
||||||
}
|
}
|
||||||
|
@ -412,7 +414,8 @@ static inline unsigned int dive_size(int samples)
|
||||||
return sizeof(struct dive) + samples*sizeof(struct sample);
|
return sizeof(struct dive) + samples*sizeof(struct sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern time_t utc_mktime(struct tm *tm);
|
extern timestamp_t utc_mktime(struct tm *tm);
|
||||||
|
extern void utc_mkdate(timestamp_t, struct tm *tm);
|
||||||
|
|
||||||
extern struct dive *alloc_dive(void);
|
extern struct dive *alloc_dive(void);
|
||||||
extern void record_dive(struct dive *dive);
|
extern void record_dive(struct dive *dive);
|
||||||
|
|
56
divelist.c
56
divelist.c
|
@ -50,7 +50,7 @@ const char *tripflag_names[NUM_TRIPFLAGS] = { "TF_NONE", "NOTRIP", "INTRIP" };
|
||||||
enum {
|
enum {
|
||||||
DIVE_INDEX = 0,
|
DIVE_INDEX = 0,
|
||||||
DIVE_NR, /* int: dive->nr */
|
DIVE_NR, /* int: dive->nr */
|
||||||
DIVE_DATE, /* time_t: dive->when */
|
DIVE_DATE, /* timestamp_t: dive->when */
|
||||||
DIVE_RATING, /* int: 0-5 stars */
|
DIVE_RATING, /* int: 0-5 stars */
|
||||||
DIVE_DEPTH, /* int: dive->maxdepth in mm */
|
DIVE_DEPTH, /* int: dive->maxdepth in mm */
|
||||||
DIVE_DURATION, /* int: in seconds */
|
DIVE_DURATION, /* int: in seconds */
|
||||||
|
@ -75,16 +75,16 @@ static gboolean dump_model_entry(GtkTreeModel *model, GtkTreePath *path,
|
||||||
char *location;
|
char *location;
|
||||||
int idx, nr, duration;
|
int idx, nr, duration;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
struct tm *tm;
|
struct tm tm;
|
||||||
|
|
||||||
gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, DIVE_DATE, &when,
|
gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_NR, &nr, DIVE_DATE, &when,
|
||||||
DIVE_DURATION, &duration, DIVE_LOCATION, &location, -1);
|
DIVE_DURATION, &duration, DIVE_LOCATION, &location, -1);
|
||||||
tm = gmtime(&when);
|
utc_mkdate(when, &tm);
|
||||||
printf("iter %x:%x entry #%d : nr %d @ %04d-%02d-%02d %02d:%02d:%02d duration %d location %s ",
|
printf("iter %x:%x entry #%d : nr %d @ %04d-%02d-%02d %02d:%02d:%02d duration %d location %s ",
|
||||||
iter->stamp, iter->user_data, idx, nr,
|
iter->stamp, iter->user_data, idx, nr,
|
||||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec,
|
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||||
duration, location);
|
duration, location);
|
||||||
dive = get_dive(idx);
|
dive = get_dive(idx);
|
||||||
if (dive)
|
if (dive)
|
||||||
|
@ -379,8 +379,8 @@ static void date_data_func(GtkTreeViewColumn *col,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
int val, idx, nr;
|
int val, idx, nr;
|
||||||
struct tm *tm;
|
struct tm tm;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
char buffer[40];
|
char buffer[40];
|
||||||
|
|
||||||
gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DATE, &val, -1);
|
gtk_tree_model_get(model, iter, DIVE_INDEX, &idx, DIVE_DATE, &val, -1);
|
||||||
|
@ -388,21 +388,21 @@ static void date_data_func(GtkTreeViewColumn *col,
|
||||||
/* 2038 problem */
|
/* 2038 problem */
|
||||||
when = val;
|
when = val;
|
||||||
|
|
||||||
tm = gmtime(&when);
|
utc_mkdate(when, &tm);
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
"Trip %s, %s %d, %d (%d dive%s)",
|
"Trip %s, %s %d, %d (%d dive%s)",
|
||||||
weekday(tm->tm_wday),
|
weekday(tm.tm_wday),
|
||||||
monthname(tm->tm_mon),
|
monthname(tm.tm_mon),
|
||||||
tm->tm_mday, tm->tm_year + 1900,
|
tm.tm_mday, tm.tm_year + 1900,
|
||||||
nr, nr > 1 ? "s" : "");
|
nr, nr > 1 ? "s" : "");
|
||||||
} else {
|
} else {
|
||||||
snprintf(buffer, sizeof(buffer),
|
snprintf(buffer, sizeof(buffer),
|
||||||
"%s, %s %d, %d %02d:%02d",
|
"%s, %s %d, %d %02d:%02d",
|
||||||
weekday(tm->tm_wday),
|
weekday(tm.tm_wday),
|
||||||
monthname(tm->tm_mon),
|
monthname(tm.tm_mon),
|
||||||
tm->tm_mday, tm->tm_year + 1900,
|
tm.tm_mday, tm.tm_year + 1900,
|
||||||
tm->tm_hour, tm->tm_min);
|
tm.tm_hour, tm.tm_min);
|
||||||
}
|
}
|
||||||
g_object_set(renderer, "text", buffer, NULL);
|
g_object_set(renderer, "text", buffer, NULL);
|
||||||
}
|
}
|
||||||
|
@ -944,7 +944,7 @@ void update_dive_list_col_visibility(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList *find_matching_trip(time_t when)
|
static GList *find_matching_trip(timestamp_t when)
|
||||||
{
|
{
|
||||||
GList *trip = dive_trip_list;
|
GList *trip = dive_trip_list;
|
||||||
if (!trip || DIVE_TRIP(trip)->when > when)
|
if (!trip || DIVE_TRIP(trip)->when > when)
|
||||||
|
@ -977,7 +977,7 @@ static gboolean dive_can_be_in_trip(int idx, struct dive *dive_trip)
|
||||||
{
|
{
|
||||||
struct dive *dive, *pdive;
|
struct dive *dive, *pdive;
|
||||||
int i = idx;
|
int i = idx;
|
||||||
time_t when = dive_trip->when;
|
timestamp_t when = dive_trip->when;
|
||||||
|
|
||||||
dive = get_dive(idx);
|
dive = get_dive(idx);
|
||||||
/* if the dive is before the trip start but within the threshold
|
/* if the dive is before the trip start but within the threshold
|
||||||
|
@ -1261,7 +1261,7 @@ void add_dive_cb(GtkWidget *menuitem, gpointer data)
|
||||||
void edit_trip_cb(GtkWidget *menuitem, GtkTreePath *path)
|
void edit_trip_cb(GtkWidget *menuitem, GtkTreePath *path)
|
||||||
{
|
{
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
struct dive *dive_trip;
|
struct dive *dive_trip;
|
||||||
GList *trip;
|
GList *trip;
|
||||||
|
|
||||||
|
@ -1336,13 +1336,13 @@ static int copy_tree_node(GtkTreeIter *a, GtkTreeIter *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* to avoid complicated special cases based on ordering or number of children,
|
/* to avoid complicated special cases based on ordering or number of children,
|
||||||
we always take the first and last child and pick the smaller time_t (which
|
we always take the first and last child and pick the smaller timestamp_t (which
|
||||||
works regardless of ordering and also with just one child) */
|
works regardless of ordering and also with just one child) */
|
||||||
static void update_trip_timestamp(GtkTreeIter *parent, struct dive *divetrip)
|
static void update_trip_timestamp(GtkTreeIter *parent, struct dive *divetrip)
|
||||||
{
|
{
|
||||||
GtkTreeIter first_child, last_child;
|
GtkTreeIter first_child, last_child;
|
||||||
int nr;
|
int nr;
|
||||||
time_t t1, t2, tnew;
|
timestamp_t t1, t2, tnew;
|
||||||
|
|
||||||
if (gtk_tree_store_iter_depth(STORE(dive_list), parent) != 0 ||
|
if (gtk_tree_store_iter_depth(STORE(dive_list), parent) != 0 ||
|
||||||
gtk_tree_model_iter_n_children(MODEL(dive_list), parent) == 0)
|
gtk_tree_model_iter_n_children(MODEL(dive_list), parent) == 0)
|
||||||
|
@ -1367,7 +1367,7 @@ static GtkTreeIter *move_dive_between_trips(GtkTreeIter *dive_iter, GtkTreeIter
|
||||||
GtkTreeIter *sibling, gboolean before)
|
GtkTreeIter *sibling, gboolean before)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
time_t old_when, new_when;
|
timestamp_t old_when, new_when;
|
||||||
struct dive *dive, *old_divetrip, *new_divetrip;
|
struct dive *dive, *old_divetrip, *new_divetrip;
|
||||||
GtkTreeIter *new_iter = malloc(sizeof(GtkTreeIter));
|
GtkTreeIter *new_iter = malloc(sizeof(GtkTreeIter));
|
||||||
|
|
||||||
|
@ -1442,7 +1442,7 @@ static void turn_dive_into_trip(GtkTreePath *path)
|
||||||
{
|
{
|
||||||
GtkTreeIter iter, *newiter, newparent;
|
GtkTreeIter iter, *newiter, newparent;
|
||||||
GtkTreePath *treepath;
|
GtkTreePath *treepath;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
char *location;
|
char *location;
|
||||||
int idx;
|
int idx;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
|
@ -1484,7 +1484,7 @@ static void insert_trip_before(GtkTreePath *path)
|
||||||
copy_tree_node(&parent, &newparent);
|
copy_tree_node(&parent, &newparent);
|
||||||
gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
|
gtk_tree_model_get(MODEL(dive_list), &iter, DIVE_INDEX, &idx, -1);
|
||||||
dive = get_dive(idx);
|
dive = get_dive(idx);
|
||||||
/* make sure that the time_t of the previous divetrip is correct before
|
/* make sure that the timestamp_t of the previous divetrip is correct before
|
||||||
* inserting a new one */
|
* inserting a new one */
|
||||||
if (dive->when < prev_dive->when)
|
if (dive->when < prev_dive->when)
|
||||||
if (prev_dive->divetrip && prev_dive->divetrip->when < prev_dive->when)
|
if (prev_dive->divetrip && prev_dive->divetrip->when < prev_dive->when)
|
||||||
|
@ -1693,7 +1693,7 @@ void merge_trips_cb(GtkWidget *menuitem, GtkTreePath *trippath)
|
||||||
GtkTreeIter thistripiter, prevtripiter, newiter, iter;
|
GtkTreeIter thistripiter, prevtripiter, newiter, iter;
|
||||||
GtkTreeModel *tm = MODEL(dive_list);
|
GtkTreeModel *tm = MODEL(dive_list);
|
||||||
GList *trip, *prevtrip;
|
GList *trip, *prevtrip;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
|
|
||||||
/* this only gets called when we are on a trip and there is another trip right before */
|
/* this only gets called when we are on a trip and there is another trip right before */
|
||||||
prevpath = gtk_tree_path_copy(trippath);
|
prevpath = gtk_tree_path_copy(trippath);
|
||||||
|
@ -1995,7 +1995,7 @@ GtkWidget *dive_list_create(void)
|
||||||
dive_list.listmodel = gtk_tree_store_new(DIVELIST_COLUMNS,
|
dive_list.listmodel = gtk_tree_store_new(DIVELIST_COLUMNS,
|
||||||
G_TYPE_INT, /* index */
|
G_TYPE_INT, /* index */
|
||||||
G_TYPE_INT, /* nr */
|
G_TYPE_INT, /* nr */
|
||||||
G_TYPE_LONG, /* Date */
|
G_TYPE_INT64, /* Date */
|
||||||
G_TYPE_INT, /* Star rating */
|
G_TYPE_INT, /* Star rating */
|
||||||
G_TYPE_INT, /* Depth */
|
G_TYPE_INT, /* Depth */
|
||||||
G_TYPE_INT, /* Duration */
|
G_TYPE_INT, /* Duration */
|
||||||
|
@ -2011,7 +2011,7 @@ GtkWidget *dive_list_create(void)
|
||||||
dive_list.treemodel = gtk_tree_store_new(DIVELIST_COLUMNS,
|
dive_list.treemodel = gtk_tree_store_new(DIVELIST_COLUMNS,
|
||||||
G_TYPE_INT, /* index */
|
G_TYPE_INT, /* index */
|
||||||
G_TYPE_INT, /* nr */
|
G_TYPE_INT, /* nr */
|
||||||
G_TYPE_LONG, /* Date */
|
G_TYPE_INT64, /* Date */
|
||||||
G_TYPE_INT, /* Star rating */
|
G_TYPE_INT, /* Star rating */
|
||||||
G_TYPE_INT, /* Depth */
|
G_TYPE_INT, /* Depth */
|
||||||
G_TYPE_INT, /* Duration */
|
G_TYPE_INT, /* Duration */
|
||||||
|
@ -2090,7 +2090,7 @@ void remove_autogen_trips()
|
||||||
{
|
{
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
GtkTreePath *path;
|
GtkTreePath *path;
|
||||||
time_t when;
|
timestamp_t when;
|
||||||
int idx;
|
int idx;
|
||||||
GList *trip;
|
GList *trip;
|
||||||
|
|
||||||
|
|
4
file.c
4
file.c
|
@ -99,7 +99,7 @@ static int try_to_open_suunto(const char *filename, struct memblock *mem, GError
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
static time_t parse_date(const char *date)
|
static timestamp_t parse_date(const char *date)
|
||||||
{
|
{
|
||||||
int hour, min, sec;
|
int hour, min, sec;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
@ -171,7 +171,7 @@ static int try_to_open_csv(const char *filename, struct memblock *mem, enum csv_
|
||||||
char *p = mem->buffer;
|
char *p = mem->buffer;
|
||||||
char *header[8];
|
char *header[8];
|
||||||
int i, time;
|
int i, time;
|
||||||
time_t date;
|
timestamp_t date;
|
||||||
struct dive *dive;
|
struct dive *dive;
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
|
|
21
info.c
21
info.c
|
@ -99,13 +99,15 @@ static char *get_combo_box_entry_text(GtkComboBoxEntry *combo_box, char **textp,
|
||||||
|
|
||||||
static int divename(char *buf, size_t size, struct dive *dive)
|
static int divename(char *buf, size_t size, struct dive *dive)
|
||||||
{
|
{
|
||||||
struct tm *tm = gmtime(&dive->when);
|
struct tm tm;
|
||||||
|
|
||||||
|
utc_mkdate(dive->when, &tm);
|
||||||
return snprintf(buf, size, "Dive #%d - %s %02d/%02d/%04d at %d:%02d",
|
return snprintf(buf, size, "Dive #%d - %s %02d/%02d/%04d at %d:%02d",
|
||||||
dive->number,
|
dive->number,
|
||||||
weekday(tm->tm_wday),
|
weekday(tm.tm_wday),
|
||||||
tm->tm_mon+1, tm->tm_mday,
|
tm.tm_mon+1, tm.tm_mday,
|
||||||
tm->tm_year+1900,
|
tm.tm_year+1900,
|
||||||
tm->tm_hour, tm->tm_min);
|
tm.tm_hour, tm.tm_min);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_dive_info(struct dive *dive)
|
void show_dive_info(struct dive *dive)
|
||||||
|
@ -681,7 +683,7 @@ static GtkWidget *frame_box(GtkWidget *vbox, const char *fmt, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fixme - should do at least depths too - a dive without a depth is kind of pointless */
|
/* Fixme - should do at least depths too - a dive without a depth is kind of pointless */
|
||||||
static time_t dive_time_widget(struct dive *dive)
|
static timestamp_t dive_time_widget(struct dive *dive)
|
||||||
{
|
{
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
GtkWidget *cal, *hbox, *vbox, *box;
|
GtkWidget *cal, *hbox, *vbox, *box;
|
||||||
|
@ -719,12 +721,13 @@ static time_t dive_time_widget(struct dive *dive)
|
||||||
* we'll just take the current time.
|
* we'll just take the current time.
|
||||||
*/
|
*/
|
||||||
if (amount_selected == 1) {
|
if (amount_selected == 1) {
|
||||||
time_t when = current_dive->when;
|
timestamp_t when = current_dive->when;
|
||||||
when += current_dive->duration.seconds;
|
when += current_dive->duration.seconds;
|
||||||
when += 60*60;
|
when += 60*60;
|
||||||
time = gmtime(&when);
|
utc_mkdate(when, &tm);
|
||||||
|
time = &tm;
|
||||||
} else {
|
} else {
|
||||||
time_t now;
|
timestamp_t now;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
now = tv.tv_sec;
|
now = tv.tv_sec;
|
||||||
|
|
44
parse-xml.c
44
parse-xml.c
|
@ -175,40 +175,10 @@ static enum import_source {
|
||||||
UDDF,
|
UDDF,
|
||||||
} import_source;
|
} import_source;
|
||||||
|
|
||||||
time_t utc_mktime(struct tm *tm)
|
|
||||||
{
|
|
||||||
static const int mdays[] = {
|
|
||||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
|
||||||
};
|
|
||||||
int year = tm->tm_year;
|
|
||||||
int month = tm->tm_mon;
|
|
||||||
int day = tm->tm_mday;
|
|
||||||
|
|
||||||
/* First normalize relative to 1900 */
|
|
||||||
if (year < 70)
|
|
||||||
year += 100;
|
|
||||||
else if (year > 1900)
|
|
||||||
year -= 1900;
|
|
||||||
|
|
||||||
/* Normalized to Jan 1, 1970: unix time */
|
|
||||||
year -= 70;
|
|
||||||
|
|
||||||
if (year < 0 || year > 129) /* algo only works for 1970-2099 */
|
|
||||||
return -1;
|
|
||||||
if (month < 0 || month > 11) /* array bounds */
|
|
||||||
return -1;
|
|
||||||
if (month < 2 || (year + 2) % 4)
|
|
||||||
day--;
|
|
||||||
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_sec < 0)
|
|
||||||
return -1;
|
|
||||||
return (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +
|
|
||||||
tm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void divedate(char *buffer, void *_when)
|
static void divedate(char *buffer, void *_when)
|
||||||
{
|
{
|
||||||
int d,m,y;
|
int d,m,y;
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
|
|
||||||
success = cur_tm.tm_sec | cur_tm.tm_min | cur_tm.tm_hour;
|
success = cur_tm.tm_sec | cur_tm.tm_min | cur_tm.tm_hour;
|
||||||
|
@ -234,7 +204,7 @@ static void divedate(char *buffer, void *_when)
|
||||||
static void divetime(char *buffer, void *_when)
|
static void divetime(char *buffer, void *_when)
|
||||||
{
|
{
|
||||||
int h,m,s = 0;
|
int h,m,s = 0;
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
|
|
||||||
if (sscanf(buffer, "%d:%d:%d", &h, &m, &s) >= 2) {
|
if (sscanf(buffer, "%d:%d:%d", &h, &m, &s) >= 2) {
|
||||||
cur_tm.tm_hour = h;
|
cur_tm.tm_hour = h;
|
||||||
|
@ -251,7 +221,7 @@ static void divedatetime(char *buffer, void *_when)
|
||||||
{
|
{
|
||||||
int y,m,d;
|
int y,m,d;
|
||||||
int hr,min,sec;
|
int hr,min,sec;
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
|
|
||||||
if (sscanf(buffer, "%d-%d-%d %d:%d:%d",
|
if (sscanf(buffer, "%d-%d-%d %d:%d:%d",
|
||||||
&y, &m, &d, &hr, &min, &sec) == 6) {
|
&y, &m, &d, &hr, &min, &sec) == 6) {
|
||||||
|
@ -822,7 +792,7 @@ static void uemis_date_unit(char *buffer, void *_unused)
|
||||||
/* Modified julian day, yay! */
|
/* Modified julian day, yay! */
|
||||||
static void uemis_date_time(char *buffer, void *_when)
|
static void uemis_date_time(char *buffer, void *_when)
|
||||||
{
|
{
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
union int_or_float val;
|
union int_or_float val;
|
||||||
|
|
||||||
switch (integer_or_float(buffer, &val)) {
|
switch (integer_or_float(buffer, &val)) {
|
||||||
|
@ -847,7 +817,7 @@ static void uemis_time_zone(char *buffer, void *_when)
|
||||||
#if 0 /* seems like this is only used to display it correctly
|
#if 0 /* seems like this is only used to display it correctly
|
||||||
* the stored time appears to be UTC */
|
* the stored time appears to be UTC */
|
||||||
|
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
signed char tz = atoi(buffer);
|
signed char tz = atoi(buffer);
|
||||||
|
|
||||||
*when += tz * 3600;
|
*when += tz * 3600;
|
||||||
|
@ -857,7 +827,7 @@ static void uemis_time_zone(char *buffer, void *_when)
|
||||||
static void uemis_ts(char *buffer, void *_when)
|
static void uemis_ts(char *buffer, void *_when)
|
||||||
{
|
{
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
|
|
||||||
memset(&tm, 0, sizeof(tm));
|
memset(&tm, 0, sizeof(tm));
|
||||||
sscanf(buffer,"%d-%d-%dT%d:%d:%d",
|
sscanf(buffer,"%d-%d-%dT%d:%d:%d",
|
||||||
|
@ -983,7 +953,7 @@ static void uddf_datetime(char *buffer, void *_when)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
int y,m,d,hh,mm,ss;
|
int y,m,d,hh,mm,ss;
|
||||||
time_t *when = _when;
|
timestamp_t *when = _when;
|
||||||
struct tm tm = { 0 };
|
struct tm tm = { 0 };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
24
print.c
24
print.c
|
@ -51,7 +51,7 @@ static void show_dive_text(struct dive *dive, cairo_t *cr, double w,
|
||||||
const char *unit;
|
const char *unit;
|
||||||
int len, decimals, width, height, maxwidth, maxheight;
|
int len, decimals, width, height, maxwidth, maxheight;
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
struct tm *tm;
|
struct tm tm;
|
||||||
char buffer[80], divenr[20], *people;
|
char buffer[80], divenr[20], *people;
|
||||||
|
|
||||||
maxwidth = w * PANGO_SCALE;
|
maxwidth = w * PANGO_SCALE;
|
||||||
|
@ -65,14 +65,14 @@ static void show_dive_text(struct dive *dive, cairo_t *cr, double w,
|
||||||
if (dive->number)
|
if (dive->number)
|
||||||
snprintf(divenr, sizeof(divenr), "Dive #%d - ", dive->number);
|
snprintf(divenr, sizeof(divenr), "Dive #%d - ", dive->number);
|
||||||
|
|
||||||
tm = gmtime(&dive->when);
|
utc_mkdate(dive->when, &tm);
|
||||||
len = snprintf(buffer, sizeof(buffer),
|
len = snprintf(buffer, sizeof(buffer),
|
||||||
"%s%s, %s %d, %d %d:%02d",
|
"%s%s, %s %d, %d %d:%02d",
|
||||||
divenr,
|
divenr,
|
||||||
weekday(tm->tm_wday),
|
weekday(tm.tm_wday),
|
||||||
monthname(tm->tm_mon),
|
monthname(tm.tm_mon),
|
||||||
tm->tm_mday, tm->tm_year + 1900,
|
tm.tm_mday, tm.tm_year + 1900,
|
||||||
tm->tm_hour, tm->tm_min);
|
tm.tm_hour, tm.tm_min);
|
||||||
|
|
||||||
set_font(layout, font, FONT_LARGE, PANGO_ALIGN_LEFT);
|
set_font(layout, font, FONT_LARGE, PANGO_ALIGN_LEFT);
|
||||||
pango_layout_set_text(layout, buffer, len);
|
pango_layout_set_text(layout, buffer, len);
|
||||||
|
@ -194,7 +194,7 @@ static void show_dive_table(struct dive *dive, cairo_t *cr, double w,
|
||||||
int len, decimals;
|
int len, decimals;
|
||||||
double maxwidth, maxheight, colwidth, curwidth;
|
double maxwidth, maxheight, colwidth, curwidth;
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
struct tm *tm;
|
struct tm tm;
|
||||||
char buffer[160], divenr[20];
|
char buffer[160], divenr[20];
|
||||||
|
|
||||||
maxwidth = w * PANGO_SCALE;
|
maxwidth = w * PANGO_SCALE;
|
||||||
|
@ -223,13 +223,13 @@ static void show_dive_table(struct dive *dive, cairo_t *cr, double w,
|
||||||
|
|
||||||
// Col 2: Date #
|
// Col 2: Date #
|
||||||
pango_layout_set_width(layout, colwidth);
|
pango_layout_set_width(layout, colwidth);
|
||||||
tm = gmtime(&dive->when);
|
utc_mkdate(dive->when, &tm);
|
||||||
len = snprintf(buffer, sizeof(buffer),
|
len = snprintf(buffer, sizeof(buffer),
|
||||||
"%s, %s %d, %d %dh%02d",
|
"%s, %s %d, %d %dh%02d",
|
||||||
weekday(tm->tm_wday),
|
weekday(tm.tm_wday),
|
||||||
monthname(tm->tm_mon),
|
monthname(tm.tm_mon),
|
||||||
tm->tm_mday, tm->tm_year + 1900,
|
tm.tm_mday, tm.tm_year + 1900,
|
||||||
tm->tm_hour, tm->tm_min
|
tm.tm_hour, tm.tm_min
|
||||||
);
|
);
|
||||||
cairo_move_to(cr, curwidth / PANGO_SCALE, 0);
|
cairo_move_to(cr, curwidth / PANGO_SCALE, 0);
|
||||||
pango_layout_set_text(layout, buffer, len);
|
pango_layout_set_text(layout, buffer, len);
|
||||||
|
|
16
save-xml.c
16
save-xml.c
|
@ -284,13 +284,15 @@ static void save_events(FILE *f, struct event *ev)
|
||||||
|
|
||||||
static void save_trip(FILE *f, struct dive *trip)
|
static void save_trip(FILE *f, struct dive *trip)
|
||||||
{
|
{
|
||||||
struct tm *tm = gmtime(&trip->when);
|
struct tm tm;
|
||||||
|
|
||||||
|
utc_mkdate(trip->when, &tm);
|
||||||
|
|
||||||
fprintf(f, "<trip");
|
fprintf(f, "<trip");
|
||||||
fprintf(f, " date='%04u-%02u-%02u'",
|
fprintf(f, " date='%04u-%02u-%02u'",
|
||||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
|
||||||
fprintf(f, " time='%02u:%02u:%02u'",
|
fprintf(f, " time='%02u:%02u:%02u'",
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||||
if (trip->location)
|
if (trip->location)
|
||||||
show_utf8(f, trip->location, " location=\'","\'", 1);
|
show_utf8(f, trip->location, " location=\'","\'", 1);
|
||||||
fprintf(f, " />\n");
|
fprintf(f, " />\n");
|
||||||
|
@ -299,7 +301,9 @@ static void save_trip(FILE *f, struct dive *trip)
|
||||||
static void save_dive(FILE *f, struct dive *dive)
|
static void save_dive(FILE *f, struct dive *dive)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct tm *tm = gmtime(&dive->when);
|
struct tm tm;
|
||||||
|
|
||||||
|
utc_mkdate(dive->when, &tm);
|
||||||
|
|
||||||
fputs("<dive", f);
|
fputs("<dive", f);
|
||||||
if (dive->number)
|
if (dive->number)
|
||||||
|
@ -309,9 +313,9 @@ static void save_dive(FILE *f, struct dive *dive)
|
||||||
if (dive->rating)
|
if (dive->rating)
|
||||||
fprintf(f, " rating='%d'", dive->rating);
|
fprintf(f, " rating='%d'", dive->rating);
|
||||||
fprintf(f, " date='%04u-%02u-%02u'",
|
fprintf(f, " date='%04u-%02u-%02u'",
|
||||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
|
tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
|
||||||
fprintf(f, " time='%02u:%02u:%02u'",
|
fprintf(f, " time='%02u:%02u:%02u'",
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
tm.tm_hour, tm.tm_min, tm.tm_sec);
|
||||||
fprintf(f, " duration='%u:%02u min'>\n",
|
fprintf(f, " duration='%u:%02u min'>\n",
|
||||||
FRACTION(dive->duration.seconds, 60));
|
FRACTION(dive->duration.seconds, 60));
|
||||||
save_overview(f, dive);
|
save_overview(f, dive);
|
||||||
|
|
28
statistics.c
28
statistics.c
|
@ -364,7 +364,7 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
struct dive *dp;
|
struct dive *dp;
|
||||||
struct tm *tm;
|
struct tm tm;
|
||||||
int current_year = 0;
|
int current_year = 0;
|
||||||
int current_month = 0;
|
int current_month = 0;
|
||||||
int year_iter = 0;
|
int year_iter = 0;
|
||||||
|
@ -408,12 +408,12 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
||||||
process_dive(dp, &stats);
|
process_dive(dp, &stats);
|
||||||
|
|
||||||
/* yearly statistics */
|
/* yearly statistics */
|
||||||
tm = gmtime(&dp->when);
|
utc_mkdate(dp->when, &tm);
|
||||||
if (current_year == 0)
|
if (current_year == 0)
|
||||||
current_year = tm->tm_year + 1900;
|
current_year = tm.tm_year + 1900;
|
||||||
|
|
||||||
if (current_year != tm->tm_year + 1900) {
|
if (current_year != tm.tm_year) {
|
||||||
current_year = tm->tm_year + 1900;
|
current_year = tm.tm_year + 1900;
|
||||||
process_dive(dp, &(stats_yearly[++year_iter]));
|
process_dive(dp, &(stats_yearly[++year_iter]));
|
||||||
} else
|
} else
|
||||||
process_dive(dp, &(stats_yearly[year_iter]));
|
process_dive(dp, &(stats_yearly[year_iter]));
|
||||||
|
@ -423,10 +423,10 @@ static void process_all_dives(struct dive *dive, struct dive **prev_dive)
|
||||||
|
|
||||||
/* monthly statistics */
|
/* monthly statistics */
|
||||||
if (current_month == 0) {
|
if (current_month == 0) {
|
||||||
current_month = tm->tm_mon + 1;
|
current_month = tm.tm_mon + 1;
|
||||||
} else {
|
} else {
|
||||||
if (current_month != tm->tm_mon + 1)
|
if (current_month != tm.tm_mon + 1)
|
||||||
current_month = tm->tm_mon + 1;
|
current_month = tm.tm_mon + 1;
|
||||||
if (prev_month != current_month || prev_year != current_year)
|
if (prev_month != current_month || prev_year != current_year)
|
||||||
month_iter++;
|
month_iter++;
|
||||||
}
|
}
|
||||||
|
@ -495,17 +495,17 @@ static void show_single_dive_stats(struct dive *dive)
|
||||||
const char *unit;
|
const char *unit;
|
||||||
int idx, offset, gas_used;
|
int idx, offset, gas_used;
|
||||||
struct dive *prev_dive;
|
struct dive *prev_dive;
|
||||||
struct tm *tm;
|
struct tm tm;
|
||||||
|
|
||||||
process_all_dives(dive, &prev_dive);
|
process_all_dives(dive, &prev_dive);
|
||||||
|
|
||||||
tm = gmtime(&dive->when);
|
utc_mkdate(dive->when, &tm);
|
||||||
snprintf(buf, sizeof(buf),
|
snprintf(buf, sizeof(buf),
|
||||||
"%s, %s %d, %d %2d:%02d",
|
"%s, %s %d, %d %2d:%02d",
|
||||||
weekday(tm->tm_wday),
|
weekday(tm.tm_wday),
|
||||||
monthname(tm->tm_mon),
|
monthname(tm.tm_mon),
|
||||||
tm->tm_mday, tm->tm_year + 1900,
|
tm.tm_mday, tm.tm_year + 1900,
|
||||||
tm->tm_hour, tm->tm_min);
|
tm.tm_hour, tm.tm_min);
|
||||||
|
|
||||||
set_label(single_w.date, buf);
|
set_label(single_w.date, buf);
|
||||||
set_label(single_w.dive_time, "%d min", (dive->duration.seconds + 30) / 60);
|
set_label(single_w.dive_time, "%d min", (dive->duration.seconds + 30) / 60);
|
||||||
|
|
98
time.c
Normal file
98
time.c
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include "dive.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert 64-bit timestamp to 'struct tm' in UTC.
|
||||||
|
*
|
||||||
|
* On 32-bit machines, only do 64-bit arithmetic for the seconds
|
||||||
|
* part, after that we do everything in 'long'. 64-bit divides
|
||||||
|
* are unnecessary once you're counting minutes (32-bit minutes:
|
||||||
|
* 8000+ years).
|
||||||
|
*/
|
||||||
|
void utc_mkdate(timestamp_t timestamp, struct tm *tm)
|
||||||
|
{
|
||||||
|
static const int mdays[] = {
|
||||||
|
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
|
||||||
|
};
|
||||||
|
static const int mdays_leap[] = {
|
||||||
|
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
|
||||||
|
};
|
||||||
|
unsigned long val;
|
||||||
|
unsigned int leapyears;
|
||||||
|
int m;
|
||||||
|
const int *mp;
|
||||||
|
|
||||||
|
memset(tm, 0, sizeof(*tm));
|
||||||
|
|
||||||
|
/* seconds since 1970 -> minutes since 1970 */
|
||||||
|
tm->tm_sec = timestamp % 60;
|
||||||
|
val = timestamp /= 60;
|
||||||
|
|
||||||
|
/* Do the simple stuff */
|
||||||
|
tm->tm_min = val % 60; val /= 60;
|
||||||
|
tm->tm_hour = val % 24; val /= 24;
|
||||||
|
|
||||||
|
/* Jan 1, 1970 was a Thursday (tm_wday=4) */
|
||||||
|
tm->tm_wday = (val+4) % 7;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we're in "days since Jan 1, 1970". To make things easier,
|
||||||
|
* let's make it "days since Jan 1, 1968", since that's a leap-year
|
||||||
|
*/
|
||||||
|
val += 365+366;
|
||||||
|
|
||||||
|
/* This only works up until 2099 (2100 isn't a leap-year) */
|
||||||
|
leapyears = val / (365*4+1);
|
||||||
|
val %= (365*4+1);
|
||||||
|
tm->tm_year = 68 + leapyears * 4;
|
||||||
|
|
||||||
|
/* Handle the leap-year itself */
|
||||||
|
mp = mdays_leap;
|
||||||
|
if (val > 365) {
|
||||||
|
tm->tm_year++;
|
||||||
|
val -= 366;
|
||||||
|
tm->tm_year += val / 365;
|
||||||
|
val %= 365;
|
||||||
|
mp = mdays;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (m = 0; m < 12; m++) {
|
||||||
|
if (val < *mp)
|
||||||
|
break;
|
||||||
|
val -= *mp++;
|
||||||
|
}
|
||||||
|
tm->tm_mday = val+1;
|
||||||
|
tm->tm_mon = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
timestamp_t utc_mktime(struct tm *tm)
|
||||||
|
{
|
||||||
|
static const int mdays[] = {
|
||||||
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
||||||
|
};
|
||||||
|
int year = tm->tm_year;
|
||||||
|
int month = tm->tm_mon;
|
||||||
|
int day = tm->tm_mday;
|
||||||
|
|
||||||
|
/* First normalize relative to 1900 */
|
||||||
|
if (year < 70)
|
||||||
|
year += 100;
|
||||||
|
else if (year > 1900)
|
||||||
|
year -= 1900;
|
||||||
|
|
||||||
|
/* Normalized to Jan 1, 1970: unix time */
|
||||||
|
year -= 70;
|
||||||
|
|
||||||
|
if (year < 0 || year > 129) /* algo only works for 1970-2099 */
|
||||||
|
return -1;
|
||||||
|
if (month < 0 || month > 11) /* array bounds */
|
||||||
|
return -1;
|
||||||
|
if (month < 2 || (year + 2) % 4)
|
||||||
|
day--;
|
||||||
|
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_sec < 0)
|
||||||
|
return -1;
|
||||||
|
return (year * 365 + (year + 1) / 4 + mdays[month] + day) * 24*60*60UL +
|
||||||
|
tm->tm_hour * 60*60 + tm->tm_min * 60 + tm->tm_sec;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue