[Xfce4-commits] <squeeze:master> Merge branch 'peter/datetime' into merge

Peter de Ridder noreply at xfce.org
Thu Dec 22 23:00:09 CET 2011


Updating branch refs/heads/master
         to 81517c9ddcb259b9dc732d4c644a64f393c0cff8 (commit)
       from e012291673d37405022b2f8505d1f83463fe028c (commit)

commit 81517c9ddcb259b9dc732d4c644a64f393c0cff8
Merge: e012291 f1786b6
Author: Peter de Ridder <peter at xfce.org>
Date:   Tue Dec 20 14:13:35 2011 +0100

    Merge branch 'peter/datetime' into merge

commit f1786b6561e7d7b3293c5675b385fe467ce6cf6b
Author: Peter de Ridder <peter at xfce.org>
Date:   Sun Oct 9 19:51:58 2011 +0200

    Changed LSQDateTime from struct tm to manual packed 64 bit

commit 15c767a3557acf54ae9dd5bba7e08879aa4f5fd4
Author: Peter de Ridder <peter at xfce.org>
Date:   Sat Oct 8 00:44:02 2011 +0200

    Parse dates and times to LSQ_TYPE_DATETIME

 libsqueeze/Makefile.am      |    1 +
 libsqueeze/archive-iter.c   |   93 +++++++++++++--
 libsqueeze/archive-iter.h   |    2 +-
 libsqueeze/datetime.c       |  280 +++++++++++++++++++++++++++++++++++++++++++
 libsqueeze/datetime.h       |   65 ++++++++++
 libsqueeze/libsqueeze.c     |    2 +
 libsqueeze/libsqueeze.h     |    1 +
 libsqueeze/parser.c         |   10 ++
 libsqueeze/parser.h         |    7 +
 libsqueeze/pcre-parser.c    |   38 +++++--
 libsqueeze/scanf-parser.c   |  253 ++++++++++++++++++++++++++++++++++-----
 libsqueeze/support-reader.c |    6 +
 src/archive_store.c         |    9 ++-
 src/notebook.c              |   13 ++-
 14 files changed, 724 insertions(+), 56 deletions(-)

diff --git a/libsqueeze/Makefile.am b/libsqueeze/Makefile.am
index b7beadb..9d64775 100644
--- a/libsqueeze/Makefile.am
+++ b/libsqueeze/Makefile.am
@@ -8,6 +8,7 @@ libsqueeze_2_la_SOURCES =  \
 	btree.c btree.h \
 	command-queue.c command-queue.h \
 	command-option.c command-option.h \
+	datetime.c datetime.h \
 	internals.c internals.h \
 	libsqueeze.c libsqueeze.h \
 	libsqueeze-view.h \
diff --git a/libsqueeze/archive-iter.c b/libsqueeze/archive-iter.c
index 0c3b5f4..4b6c3a1 100644
--- a/libsqueeze/archive-iter.c
+++ b/libsqueeze/archive-iter.c
@@ -77,14 +77,18 @@ inline static guint
 lsq_archive_entry_get_prop_uint(const LSQArchive *, const LSQArchiveEntry *, guint);
 inline static guint64
 lsq_archive_entry_get_prop_uint64(const LSQArchive *, const LSQArchiveEntry *, guint);
+inline static LSQDateTime
+lsq_archive_entry_get_prop_datetime(const LSQArchive *, const LSQArchiveEntry *, guint);
 
 static void
-lsq_archive_entry_set_prop_str(const LSQArchive *, LSQArchiveEntry *, guint, const gchar *);
+lsq_archive_entry_set_prop_str(const LSQArchive *, LSQArchiveEntry *, guint, gchar *);
 static void
 lsq_archive_entry_set_prop_uint(const LSQArchive *, LSQArchiveEntry *, guint, guint);
 static void
 lsq_archive_entry_set_prop_uint64(const LSQArchive *, LSQArchiveEntry *, guint, guint64);
 static void
+lsq_archive_entry_set_prop_datetime(const LSQArchive *, LSQArchiveEntry *, guint, LSQDateTime);
+static void
 lsq_archive_entry_set_propsv(const LSQArchive *, LSQArchiveEntry *, gpointer *);
 static void
 lsq_archive_entry_set_propsva(const LSQArchive *, LSQArchiveEntry *, va_list);
@@ -660,6 +664,11 @@ lsq_archive_iter_get_prop_value(const LSQArchiveIter *iter, guint n, GValue *val
 			g_value_set_uint64(value, lsq_archive_entry_get_prop_uint64(iter->archive, iter->entry, n));
 			break;
 		default:
+			if ( LSQ_TYPE_DATETIME == G_VALUE_TYPE(value) )
+			{
+                            g_value_set_datetime(value, lsq_archive_entry_get_prop_datetime(iter->archive, iter->entry, n));
+                            break;
+			}
 			return FALSE;
 	}
 
@@ -679,7 +688,7 @@ lsq_archive_iter_set_prop_value(LSQArchiveIter *iter, guint n, const GValue *val
 	switch(G_VALUE_TYPE(value))
 	{
 		case G_TYPE_STRING:
-			lsq_archive_entry_set_prop_str(iter->archive, iter->entry, n, g_value_get_string(value));
+			lsq_archive_entry_set_prop_str(iter->archive, iter->entry, n, g_value_dup_string(value));
 			break;
 		case G_TYPE_UINT:
 			lsq_archive_entry_set_prop_uint(iter->archive, iter->entry, n, g_value_get_uint(value));
@@ -687,11 +696,18 @@ lsq_archive_iter_set_prop_value(LSQArchiveIter *iter, guint n, const GValue *val
 		case G_TYPE_UINT64:
 			lsq_archive_entry_set_prop_uint64(iter->archive, iter->entry, n, g_value_get_uint64(value));
 			break;
+		default:
+			if ( LSQ_TYPE_DATETIME == G_VALUE_TYPE(value) )
+			{
+                            lsq_archive_entry_set_prop_datetime(iter->archive, iter->entry, n, g_value_get_datetime(value));
+                            break;
+                        }
+                        break;
 	}
 }
 
 void
-lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gconstpointer value)
+lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gpointer value)
 {
 #ifdef DEBUG
 	g_return_if_fail(iter);
@@ -705,11 +721,18 @@ lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gconstpointer value)
 			lsq_archive_entry_set_prop_str(iter->archive, iter->entry, n, value);
 			break;
 		case G_TYPE_UINT:
-			lsq_archive_entry_set_prop_uint(iter->archive, iter->entry, n, *(const guint*)value);
+			lsq_archive_entry_set_prop_uint(iter->archive, iter->entry, n, *(guint*)value);
 			break;
 		case G_TYPE_UINT64:
-			lsq_archive_entry_set_prop_uint64(iter->archive, iter->entry, n, *(const guint64*)value);
+			lsq_archive_entry_set_prop_uint64(iter->archive, iter->entry, n, *(guint64*)value);
 			break;
+		default:
+			if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(iter->archive, n) )
+			{
+                            lsq_archive_entry_set_prop_datetime(iter->archive, iter->entry, n, *(LSQDateTime*)value);
+                            break;
+                        }
+                        break;
 	}
 }
 
@@ -965,7 +988,7 @@ lsq_archive_entry_props_free(const LSQArchive *archive, LSQArchiveEntry *entry)
 		{
 			switch ( lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
 			{
-				case ( G_TYPE_STRING ):
+				case G_TYPE_STRING:
 					/* free only strings */
 					offset = lsq_archive_get_entry_property_offset(archive, i+LSQ_ARCHIVE_PROP_USER);
 					g_free(((gchar **)props_iter)[offset]);
@@ -1415,6 +1438,26 @@ lsq_archive_entry_get_prop_uint64(const LSQArchive *archive, const LSQArchiveEnt
 	return (((guint64 *)props_iter)[offset]);
 }
 
+inline static LSQDateTime
+lsq_archive_entry_get_prop_datetime(const LSQArchive *archive, const LSQArchiveEntry *entry, guint i)
+{
+	gpointer props_iter = entry->props;
+	guint offset;
+	if ( NULL == props_iter )
+	{
+		return 0;
+	}
+
+	if ( LSQ_TYPE_DATETIME != lsq_archive_get_entry_property_type(archive, i) )
+	{
+		return 0;
+	}
+
+	offset = lsq_archive_get_entry_property_offset(archive, i);
+
+	return (((LSQDateTime *)props_iter)[offset]);
+}
+
 static gpointer
 lsq_archive_entry_get_props(const LSQArchive *archive, LSQArchiveEntry *entry)
 {
@@ -1431,7 +1474,7 @@ lsq_archive_entry_get_props(const LSQArchive *archive, LSQArchiveEntry *entry)
 }
 
 static void
-lsq_archive_entry_set_prop_str(const LSQArchive *archive, LSQArchiveEntry *entry, guint n, const gchar *str_val)
+lsq_archive_entry_set_prop_str(const LSQArchive *archive, LSQArchiveEntry *entry, guint n, gchar *str_val)
 {
 	gpointer props_iter = lsq_archive_entry_get_props(archive, entry);
 	guint offset;
@@ -1444,7 +1487,7 @@ lsq_archive_entry_set_prop_str(const LSQArchive *archive, LSQArchiveEntry *entry
 	offset = lsq_archive_get_entry_property_offset(archive, n);
 
 	g_free(((gchar **)props_iter)[offset]);
-	((gchar **)props_iter)[offset] = g_strdup(str_val);
+	((gchar **)props_iter)[offset] = str_val; /* We take ownership */
 }
 
 static void
@@ -1480,6 +1523,22 @@ lsq_archive_entry_set_prop_uint64(const LSQArchive *archive, LSQArchiveEntry *en
 }
 
 static void
+lsq_archive_entry_set_prop_datetime(const LSQArchive *archive, LSQArchiveEntry *entry, guint n, LSQDateTime dt_val)
+{
+	gpointer props_iter = lsq_archive_entry_get_props(archive, entry);
+	guint offset;
+
+	if ( LSQ_TYPE_DATETIME != lsq_archive_get_entry_property_type(archive, n) )
+	{
+		return;
+	}
+
+	offset = lsq_archive_get_entry_property_offset(archive, n);
+
+	((LSQDateTime *)props_iter)[offset] = dt_val; /* We take ownership */
+}
+
+static void
 lsq_archive_entry_set_propsv(const LSQArchive *archive, LSQArchiveEntry *entry, gpointer *props)
 {
 	gpointer props_iter = lsq_archive_entry_get_props(archive, entry);
@@ -1494,7 +1553,7 @@ lsq_archive_entry_set_propsv(const LSQArchive *archive, LSQArchiveEntry *entry,
 			case G_TYPE_STRING:
 				g_free(((gchar **)props_iter)[offset]);
 				//(*((gchar **)props_iter)) = g_strdup((const gchar*)props[i]);
-				((gchar **)props_iter)[offset] = (gchar*)props[i];
+				((gchar **)props_iter)[offset] = (gchar*)props[i]; /* We take ownership */
 				break;
 			case G_TYPE_UINT:
 				((guint *)props_iter)[offset] = *((const guint *)props[i]);
@@ -1502,6 +1561,13 @@ lsq_archive_entry_set_propsv(const LSQArchive *archive, LSQArchiveEntry *entry,
 			case G_TYPE_UINT64:
 				((guint64 *)props_iter)[offset] = *((const guint64 *)props[i]);
 				break;
+                        default:
+                                if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
+                                {
+                                    ((LSQDateTime *)props_iter)[offset] = *(LSQDateTime*)props[i];
+                                    break;
+                                }
+				break;
 		}
 	}
 }
@@ -1520,7 +1586,7 @@ lsq_archive_entry_set_propsva(const LSQArchive *archive, LSQArchiveEntry *entry,
 		{
 			case G_TYPE_STRING:
 				g_free(((gchar **)props_iter)[offset]);
-				((gchar **)props_iter)[offset] = g_strdup(va_arg(ap, gchar*));
+				((gchar **)props_iter)[offset] = va_arg(ap, gchar*); /* We take ownership */
 				break;
 			case G_TYPE_UINT:
 				((guint *)props_iter)[offset] = va_arg(ap, guint);
@@ -1528,6 +1594,13 @@ lsq_archive_entry_set_propsva(const LSQArchive *archive, LSQArchiveEntry *entry,
 			case G_TYPE_UINT64:
 				((guint64 *)props_iter)[offset] = va_arg(ap, guint64);
 				break;
+                        default:
+                                if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, i+LSQ_ARCHIVE_PROP_USER) )
+                                {
+                                    ((LSQDateTime *)props_iter)[offset] = va_arg(ap, LSQDateTime);
+                                    break;
+                                }
+				break;
 		}
 	}
 }
diff --git a/libsqueeze/archive-iter.h b/libsqueeze/archive-iter.h
index 3913102..4a4b105 100644
--- a/libsqueeze/archive-iter.h
+++ b/libsqueeze/archive-iter.h
@@ -50,7 +50,7 @@ LSQArchiveIter *lsq_archive_add_file(LSQArchive *archive, const gchar *path);
 LSQArchiveIter *lsq_archive_iter_add_file(LSQArchiveIter *parent, const gchar *filename);
 
 void  lsq_archive_iter_set_prop_value(LSQArchiveIter *iter, guint n, const GValue *value);
-void  lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gconstpointer value);
+void  lsq_archive_iter_set_prop(LSQArchiveIter *iter, guint n, gpointer value);
 void  lsq_archive_iter_set_props(LSQArchiveIter *iter, ...);
 void  lsq_archive_iter_set_propsv(LSQArchiveIter *iter, gpointer *props);
 
diff --git a/libsqueeze/datetime.c b/libsqueeze/datetime.c
new file mode 100644
index 0000000..1a120c7
--- /dev/null
+++ b/libsqueeze/datetime.c
@@ -0,0 +1,280 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or 
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <config.h>
+#define _XOPEN_SOURCE
+#include <time.h>
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
+#include <gio/gio.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "libsqueeze.h"
+#include "support-factory.h"
+#include "support-reader.h"
+#include "archive-iter.h"
+#include "archive.h"
+
+#include "internals.h"
+
+#define TM_SEC_SIZE     (6)
+#define TM_MIN_SIZE     (6)
+#define TM_HOUR_SIZE    (5)
+#define TM_MDAY_SIZE    (5)
+#define TM_MON_SIZE     (4)
+#define TM_YEAR_SIZE    (64 - TM_SEC_SIZE - TM_MIN_SIZE - TM_HOUR_SIZE - TM_MDAY_SIZE - TM_MON_SIZE - TM_WDAY_SIZE - TM_YDAY_SIZE - TM_ISDST_SIZE)
+#define TM_WDAY_SIZE    (3)
+#define TM_YDAY_SIZE    (9)
+#define TM_ISDST_SIZE   (2)
+
+#define TM_SEC_OFFSET   (0)
+#define TM_MIN_OFFSET   (TM_SEC_OFFSET + TM_SEC_SIZE)
+#define TM_HOUR_OFFSET  (TM_MIN_OFFSET + TM_MIN_SIZE)
+#define TM_MDAY_OFFSET  (TM_HOUR_OFFSET + TM_HOUR_SIZE)
+#define TM_MON_OFFSET   (TM_MDAY_OFFSET + TM_MDAY_SIZE)
+#define TM_YEAR_OFFSET  (TM_MON_OFFSET + TM_MON_SIZE)
+#define TM_WDAY_OFFSET  (TM_YEAR_OFFSET + TM_YEAR_SIZE)
+#define TM_YDAY_OFFSET  (TM_WDAY_OFFSET + TM_WDAY_SIZE)
+#define TM_ISDST_OFFSET (TM_YDAY_OFFSET + TM_YDAY_SIZE)
+
+#define TM_X_MAKE(x,v) (((guint64)((v) & ((1<<(TM_##x##_SIZE)) - 1))) << (TM_##x##_OFFSET))
+#define TM_X_GET(x,v) (((v) >> (TM_##x##_OFFSET)) & ((1<<(TM_##x##_SIZE)) - 1))
+#define TM_X_MASK(x) (((guint64)((1<<(TM_##x##_SIZE)) - 1)) << (TM_##x##_OFFSET))
+#define LSQ_DATETIME_CMP_MASK(v) ((v)&(TM_X_MASK(YEAR)|TM_X_MASK(MON)|TM_X_MASK(MDAY)|TM_X_MASK(HOUR)|TM_X_MASK(MIN)|TM_X_MASK(SEC)))
+
+static void
+value_init_datetime ( GValue *value )
+{
+    value->data[0].v_int64 = LSQ_DATETIME_NULL;
+}
+
+static void
+value_copy_datetime (
+        const GValue *src_value,
+        GValue *dest_value )
+{
+    dest_value->data[0].v_int64 = src_value->data[0].v_int64;
+}
+
+static gchar *
+value_collect_datetime (
+        GValue *value,
+        guint n_collect_values,
+        GTypeCValue *collect_values,
+        guint collect_flags )
+{
+    value->data[0].v_int64 = collect_values[0].v_int64;
+
+    return NULL;
+}
+
+static gchar *
+value_lcopy_datetime (
+        const GValue *value,
+        guint n_collect_values,
+        GTypeCValue *collect_values,
+        guint collect_flags )
+{
+    gint64 *int64_p = collect_values[0].v_pointer;
+
+    if (!int64_p)
+        return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
+
+    *int64_p = value->data[0].v_int64;
+
+    return NULL;
+}
+
+static void
+value_datetime_to_string (
+        const GValue *src_value,
+        GValue *dest_value )
+{
+    gchar buffer[80]; /* An abitrary size to fit the time string in */
+    struct tm timeval;
+    LSQDateTime dt = g_value_get_datetime( src_value );
+
+    if ( LSQ_DATETIME_NULL != dt )
+    {
+        lsq_datetime_to_tm( dt, &timeval );
+        strftime( buffer, sizeof(buffer), "%c", &timeval );
+        g_value_set_string( dest_value, buffer );
+    }
+}
+
+GType
+lsq_datetime_get_type ( void )
+{
+    static GType type = G_TYPE_INVALID;
+
+    if ( G_UNLIKELY( G_TYPE_INVALID == type ) )
+    {
+        GTypeValueTable value_table = {
+            value_init_datetime,
+            NULL,
+            value_copy_datetime,
+            NULL,
+            "q",
+            value_collect_datetime,
+            "p",
+            value_lcopy_datetime
+        };
+        GTypeInfo type_info = {
+            0,
+            NULL,
+            NULL,
+            NULL,
+            NULL,
+            NULL,
+            0,
+            0,
+            NULL,
+            &value_table
+        };
+        GTypeFundamentalInfo fundamental_info = { 0 };
+
+        type = g_type_register_fundamental(
+                g_type_fundamental_next(),
+                "LSQDateTime",
+                &type_info,
+                &fundamental_info,
+                0
+            );
+
+	g_value_register_transform_func(
+                type,
+                G_TYPE_STRING,
+                value_datetime_to_string
+            );
+    }
+
+    return type;
+}
+
+void
+lsq_datetime_register_type ( void )
+{
+    /* Force lsq_datetime_get_type to get called, and not optimized by G_GNUC_CONST */
+    volatile GType type;
+    type  = lsq_datetime_get_type();
+}
+
+LSQDateTime
+lsq_datetime_from_tm ( const struct tm *timeval )
+{
+    g_return_val_if_fail( NULL != timeval, LSQ_DATETIME_NULL );
+
+    return (
+            TM_X_MAKE( SEC, timeval->tm_sec ) |
+            TM_X_MAKE( MIN, timeval->tm_min ) |
+            TM_X_MAKE( HOUR, timeval->tm_hour ) |
+            TM_X_MAKE( MDAY, timeval->tm_mday ) |
+            TM_X_MAKE( MON, timeval->tm_mon ) |
+            TM_X_MAKE( YEAR, timeval->tm_year ) |
+            TM_X_MAKE( WDAY, timeval->tm_wday ) |
+            TM_X_MAKE( YDAY, timeval->tm_yday ) |
+            TM_X_MAKE( ISDST, timeval->tm_isdst ));
+}
+
+LSQDateTime
+lsq_datetime_from_string (
+        const gchar *str,
+        const gchar *format,
+        gchar **endp )
+{
+    struct tm timeval;
+    LSQDateTime dt = LSQ_DATETIME_NULL;
+
+    g_return_val_if_fail( NULL != str, LSQ_DATETIME_NULL );
+    g_return_val_if_fail( NULL != format, LSQ_DATETIME_NULL );
+
+    str = strptime( str, format, &timeval );
+
+    if ( G_LIKELY( NULL != str ) )
+    {
+        if ( NULL != endp )
+        {
+            *endp = (gchar*)str;
+        }
+
+        dt = lsq_datetime_from_tm( &timeval );
+    }
+
+    return dt;
+}
+
+void
+lsq_datetime_to_tm ( LSQDateTime dt, struct tm *timeval )
+{
+    g_return_if_fail( LSQ_DATETIME_NULL!= dt );
+    g_return_if_fail( NULL != timeval );
+
+    memset( timeval, 0, sizeof(struct tm) );
+
+    timeval->tm_sec = TM_X_GET( SEC, dt );
+    timeval->tm_min = TM_X_GET( MIN, dt );
+    timeval->tm_hour = TM_X_GET( HOUR, dt );
+    timeval->tm_mday = TM_X_GET( MDAY, dt );
+    timeval->tm_mon = TM_X_GET( MON, dt );
+    timeval->tm_year = TM_X_GET( YEAR, dt );
+    timeval->tm_wday = TM_X_GET( WDAY, dt );
+    timeval->tm_yday = TM_X_GET( YDAY, dt );
+    timeval->tm_isdst = TM_X_GET( ISDST, dt );
+}
+
+gint
+lsq_datetime_cmp (
+        LSQDateTime a,
+        LSQDateTime b )
+{
+    gint cmp;
+
+    if ( a == b )
+        return 0;
+
+    if ( LSQ_DATETIME_NULL == a )
+        return -1;
+    if ( LSQ_DATETIME_NULL == b )
+        return 1;
+
+    /* Ignoring daylight saveing */
+    cmp = LSQ_DATETIME_CMP_MASK( a ) - LSQ_DATETIME_CMP_MASK( b );
+    if ( 0 != cmp )
+        return cmp;
+
+    return difftime( mktime( (struct tm*)a ), mktime( (struct tm*)b ) );
+}
+
+LSQDateTime
+g_value_get_datetime ( const GValue *value )
+{
+    g_return_val_if_fail( G_VALUE_HOLDS_DATETIME( value ), LSQ_DATETIME_NULL );
+
+    return value->data[0].v_int64;
+}
+
+void
+g_value_set_datetime (
+        GValue *value,
+        LSQDateTime v_dt )
+{
+    g_return_if_fail( G_VALUE_HOLDS_DATETIME( value ) );
+
+    value->data[0].v_int64 = v_dt;
+}
+
diff --git a/libsqueeze/datetime.h b/libsqueeze/datetime.h
new file mode 100644
index 0000000..fbc534c
--- /dev/null
+++ b/libsqueeze/datetime.h
@@ -0,0 +1,65 @@
+/*
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software 
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+ */
+
+#ifndef __LIBSQUEEZE_DATETIME_H__
+#define __LIBSQUEEZE_DATETIME_H__ 
+G_BEGIN_DECLS
+
+
+#define LSQ_TYPE_DATETIME lsq_datetime_get_type()
+#define LSQ_DATETIME(v) ((LSQDateTime)(v))
+
+#define LSQ_DATETIME_NULL (LSQ_DATETIME(0))
+
+#define G_VALUE_HOLDS_DATETIME(value) (G_TYPE_CHECK_VALUE_TYPE((value), LSQ_TYPE_DATETIME))
+
+typedef gint64 LSQDateTime;
+
+GType
+lsq_datetime_get_type ( void ) G_GNUC_CONST;
+
+void
+lsq_datetime_register_type ( void );
+
+LSQDateTime
+lsq_datetime_from_tm ( const struct tm * );
+
+LSQDateTime
+lsq_datetime_from_string (
+        const gchar *,
+        const gchar *,
+        gchar ** );
+
+void
+lsq_datetime_to_tm ( LSQDateTime, struct tm * );
+
+gint
+lsq_datetime_cmp (
+        LSQDateTime,
+        LSQDateTime );
+
+LSQDateTime
+g_value_get_datetime ( const GValue * );
+
+void
+g_value_set_datetime (
+        GValue *,
+        LSQDateTime );
+
+
+G_END_DECLS
+
+#endif /* __LIBSQUEEZE_DATETIME_H__ */
diff --git a/libsqueeze/libsqueeze.c b/libsqueeze/libsqueeze.c
index 2dd2105..a62aef0 100644
--- a/libsqueeze/libsqueeze.c
+++ b/libsqueeze/libsqueeze.c
@@ -74,6 +74,8 @@ lsq_init(void)
   const gchar* const* system_dirs = g_get_system_data_dirs ();
   const gchar* user_dir = g_get_user_data_dir ();
 
+  lsq_datetime_register_type();
+
   support_factory_list = NULL;
 
   lsq_opened_archive_list = NULL;
diff --git a/libsqueeze/libsqueeze.h b/libsqueeze/libsqueeze.h
index e86ed79..965e054 100644
--- a/libsqueeze/libsqueeze.h
+++ b/libsqueeze/libsqueeze.h
@@ -24,6 +24,7 @@
 #include <libsqueeze/archive-iter-pool.h>
 #include <libsqueeze/archive.h>
 #include <libsqueeze/archive-iter.h>
+#include <libsqueeze/datetime.h>
 
 #include <libsqueeze/libsqueeze-view.h>
 
diff --git a/libsqueeze/parser.c b/libsqueeze/parser.c
index 3a3e92c..ca2578f 100644
--- a/libsqueeze/parser.c
+++ b/libsqueeze/parser.c
@@ -103,6 +103,7 @@ lsq_storage_group_has_type (
 static void
 lsq_parser_init ( LSQParser *self )
 {
+    self->datetime_format = g_strdup( "%c" );
 }
 
 static void
@@ -120,6 +121,7 @@ lsq_parser_class_init ( LSQParserClass *klass )
     lsq_storage_group_add(G_TYPE_UINT, sizeof(guint));
     lsq_storage_group_add(G_TYPE_UINT64, sizeof(guint64));
     lsq_storage_group_add(G_TYPE_ULONG, sizeof(gulong));
+    lsq_storage_group_add(LSQ_TYPE_DATETIME, sizeof(LSQDateTime*));
 }
 
 LSQParserContext*
@@ -229,3 +231,11 @@ lsq_parser_get_properties_size ( LSQParser *parser )
     return parser->properties_size;
 }
 
+void
+lsq_parser_set_datetime_format (
+        LSQParser *parser,
+        const gchar *format )
+{
+    g_free( parser->datetime_format );
+    parser->datetime_format = g_strdup( format );
+}
diff --git a/libsqueeze/parser.h b/libsqueeze/parser.h
index b3c0301..8d8a283 100644
--- a/libsqueeze/parser.h
+++ b/libsqueeze/parser.h
@@ -56,6 +56,8 @@ struct _LSQParser
     GType *property_types;
     guint *property_offset;
     guint properties_size;
+
+    gchar *datetime_format;
 };
 
 
@@ -112,6 +114,11 @@ lsq_parser_get_property_offset (
 guint
 lsq_parser_get_properties_size ( LSQParser * );
 
+void
+lsq_parser_set_datetime_format (
+        LSQParser *,
+        const gchar * );
+
 G_END_DECLS
 
 #endif /* __LIBSQUEEZE_PARSER_H__ */
diff --git a/libsqueeze/pcre-parser.c b/libsqueeze/pcre-parser.c
index 46f4edc..c98769f 100644
--- a/libsqueeze/pcre-parser.c
+++ b/libsqueeze/pcre-parser.c
@@ -36,7 +36,7 @@ typedef struct _type_parser type_parser;
 typedef struct _LSQPcreParserContext LSQPcreParserContext;
 typedef struct _LSQPcreParserContextClass LSQPcreParserContextClass;
 
-typedef void (*LSQParseFunc)( gchar*, guint, LSQArchiveIter*, guint );
+typedef void (*LSQParseFunc)( gchar*, guint, LSQArchiveIter*, guint, LSQPcreParser* );
 
 struct _type_parser
 {
@@ -132,28 +132,28 @@ lsq_pcre_parser_new ( const gchar *parser_string, gchar **parser_types )
 }
 
 #define DEF_PARSE_NUM(func, base, type) \
-static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n) {  \
+static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser) {  \
     type val; \
     val = g_ascii_strtoll( str, NULL, base ); \
     lsq_archive_iter_set_prop( iter, n, &val ); \
 }
 
 #define DEF_PARSE_FLOAT(func, type)  \
-static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n) {  \
+static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser) {  \
     type  val;  \
     val = g_ascii_strtod(str, NULL);  \
     lsq_archive_iter_set_prop( iter, n, &val ); \
 }
 
 #define DEF_PARSE_UNS(func, base, type) \
-static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n) {  \
+static void parse_##func(gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser) {  \
     type val; \
     val = g_ascii_strtoull( str, NULL, base ); \
     lsq_archive_iter_set_prop( iter, n, &val ); \
 }
 
 static void
-parse_char( gchar *str, guint lng, LSQArchiveIter *iter, guint n )
+parse_char( gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser )
 {
     gchar val;
 
@@ -177,7 +177,7 @@ DEF_PARSE_UNS(octal32, 010, gulong)
 DEF_PARSE_UNS(octal64, 010, guint64)
 
 static void
-parse_string( gchar *str, guint lng, LSQArchiveIter *iter, guint n )
+parse_string( gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser )
 {
     gchar *val;
 
@@ -185,8 +185,25 @@ parse_string( gchar *str, guint lng, LSQArchiveIter *iter, guint n )
     val = g_strndup( str, lng );
 
     lsq_archive_iter_set_prop( iter, n, val );
+}
+
+static void
+parse_datetime( gchar *str, guint lng, LSQArchiveIter *iter, guint n, LSQPcreParser *parser )
+{
+    LSQDateTime val;
+
+#ifdef DO_EXSTENSIVE_CHECKING
+    gchar *end;
+    val = lsq_datetime_from_string( str, LSQ_PARSER(parser)->datetime_format, *end);
+    if ( LSQ_DATETIME_NULL != val && ( end - str ) > lng )
+    {
+        val = LSQ_DATETIME_NULL;
+    }
+#else
+    val = lsq_datetime_from_string( str, LSQ_PARSER(parser)->datetime_format, NULL);
+#endif
 
-    g_free( val );
+    lsq_archive_iter_set_prop( iter, n, &val );
 }
 
 DEF_PARSE_UNS(unsigned, 10, guint)
@@ -380,6 +397,11 @@ build_parser ( LSQPcreParser *parser, const gchar *parser_string, gchar **parser
                 type = G_TYPE_STRING;
                 break;
 
+            case 't':   /* DateTime */
+                type_iter->function = parse_datetime;
+                type = LSQ_TYPE_DATETIME;
+                break;
+
             case 'u':   /* Unsigned integer */
                 switch(size_flag)
                 {
@@ -536,7 +558,7 @@ lsq_pcre_parser_parse ( LSQPcreParser *parser, LSQPcreParserContext *ctx )
             end = ovector[( index_ * 2 ) + 1];
 
             /* Parse the subfield */
-            parser->types_list[i].function( line + start, end - start, iter, LSQ_ARCHIVE_PROP_USER +  i );
+            parser->types_list[i].function( line + start, end - start, iter, LSQ_ARCHIVE_PROP_USER +  i, parser );
         }
 
         lsq_archive_iter_unref( iter );
diff --git a/libsqueeze/scanf-parser.c b/libsqueeze/scanf-parser.c
index 462dca1..873c9af 100644
--- a/libsqueeze/scanf-parser.c
+++ b/libsqueeze/scanf-parser.c
@@ -35,7 +35,7 @@ typedef struct _parse_part parse_part;
 typedef struct _LSQScanfParserContext LSQScanfParserContext;
 typedef struct _LSQScanfParserContextClass LSQScanfParserContextClass;
 
-typedef guint (*LSQParseFunc)(gchar*, guint, parse_part*, LSQScanfParserContext*);
+typedef guint (*LSQParseFunc)(gchar*, guint, parse_part*, LSQScanfParserContext*, LSQScanfParser*);
 
 struct _parse_part
 {
@@ -60,6 +60,7 @@ struct _LSQScanfParserContext
         guint64 ull;
         gfloat  f;
         gdouble d;
+        LSQDateTime dt;
     } *data_store;
     gpointer *props_store;
     parse_part *parse_loc;
@@ -147,7 +148,8 @@ skip_byte (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 1 > lng )
     {
@@ -162,7 +164,8 @@ skip_word (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 2 > lng )
     {
@@ -177,7 +180,8 @@ skip_dword (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 4 > lng )
     {
@@ -192,7 +196,8 @@ skip_qword (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     if ( 8 > lng )
     {
@@ -207,7 +212,8 @@ skip_char (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     const gchar *ptr;
     const gchar *delim;
@@ -245,7 +251,8 @@ skip_decimal (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -270,7 +277,14 @@ skip_decimal (
         return ptr - str;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(ptr, lng, delim);
 
@@ -295,7 +309,8 @@ skip_floatingpoint (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -320,7 +335,14 @@ skip_floatingpoint (
         return ptr - str;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(ptr, lng, delim);
 
@@ -344,7 +366,8 @@ skip_octal (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx ,
+        LSQScanfParser *parser)
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -369,7 +392,14 @@ skip_octal (
         return ptr - str;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(ptr, lng, delim);
 
@@ -394,7 +424,8 @@ skip_string (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
     const gchar *delim;
@@ -416,7 +447,14 @@ skip_string (
         return 0;
     }
 
-    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr );
+    for ( ptr = str; g_ascii_isspace( *ptr ); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len ( ptr, lng, delim );
 
@@ -429,11 +467,63 @@ skip_string (
 }
 
 static guint
+skip_datetime (
+        gchar *str,
+        guint lng,
+        parse_part *part,
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
+{
+    gchar *ptr;
+    gchar *cur;
+    const gchar *delim;
+
+    if ( 0 == lng )
+    {
+        return 0;
+    }
+
+    delim = part->delimiter;
+    if ( ( NULL == delim ) && ( NULL == part->next ) )
+    {
+        delim = "\n";
+    }
+
+    for ( cur = str; g_ascii_isspace( *cur ); ++cur )
+    {
+    }
+
+    lsq_datetime_from_string(cur, LSQ_PARSER(parser)->datetime_format, &ptr);
+    if ( NULL == ptr )
+    {
+        return 0;
+    }
+
+    if ( ( ptr - str ) > lng )
+    {
+        return 0;
+    }
+
+    if ( '\0' == delim[0] )
+    {
+        lng -= ptr - str;
+        ptr = g_strstr_len( ptr, lng, delim );
+        if ( NULL == ptr )
+        {
+            return 0;
+        }
+    }
+
+    return ptr - str;
+}
+
+static guint
 skip_unsigned (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -458,7 +548,16 @@ skip_unsigned (
         return ptr - str;
     }
 
-    ptr = g_strstr_len ( str, lng, delim );
+    for ( ptr = str; g_ascii_isspace(*ptr); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
+
+    ptr = g_strstr_len(ptr, lng, delim);
 
     if ( NULL == ptr )
     {
@@ -482,7 +581,8 @@ skip_hexadecimal (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
 {
     gchar *ptr;
 #ifdef DO_EXSTENSIVE_CHECKING
@@ -507,7 +607,16 @@ skip_hexadecimal (
         return ptr - str;
     }
 
-    ptr = g_strstr_len ( str, lng, delim );
+    for ( ptr = str; g_ascii_isspace(*ptr); ++ptr )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
+
+    ptr = g_strstr_len(ptr, lng, delim);
 
     if ( NULL == ptr )
     {
@@ -527,7 +636,7 @@ skip_hexadecimal (
 
 /*{{{ parse functions*/
 #define DEF_PARSE_BIN(func, bytes, type, ptype, pname)    \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) { \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) { \
     type    val;    \
     ptype *pval;    \
     if(bytes > lng) return 0; \
@@ -539,7 +648,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
 }
 
 #define DEF_PARSE_NUM(func, base, type, ptype, pname) \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) {    \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) {    \
     gchar *ptr;     \
     gchar *ptr2;    \
     type    val;    \
@@ -555,7 +664,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
         *pval = val;    \
         return ptr - str; \
     } \
-    for(ptr = str; g_ascii_isspace(*ptr); ++ptr);     \
+    for(ptr = str; g_ascii_isspace(*ptr); ++ptr) --lng; \
     ptr = g_strstr_len(ptr, lng, delim);    \
     if(NULL == ptr) return 0;   \
     val = g_ascii_strtoll(str, &ptr2, base);    \
@@ -565,7 +674,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
 }
 
 #define DEF_PARSE_FLOAT(func, type, pname)    \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) {    \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) {    \
     gchar *ptr;     \
     gchar *ptr2;    \
     type    val;    \
@@ -581,7 +690,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
         *pval = val;    \
         return ptr - str; \
     } \
-    for(ptr = str; g_ascii_isspace(*ptr); ++ptr);     \
+    for(ptr = str; g_ascii_isspace(*ptr); ++ptr) --lng; \
     ptr = g_strstr_len(ptr, lng, delim);    \
     if(NULL == ptr) return 0;   \
     val = g_ascii_strtod(str, &ptr2); \
@@ -591,7 +700,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
 }
 
 #define DEF_PARSE_UNS(func, base, type, ptype, pname) \
-static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx) {    \
+static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParserContext *ctx, LSQScanfParser *parser) {    \
     gchar *ptr;     \
     gchar *ptr2;    \
     type    val;    \
@@ -607,7 +716,7 @@ static guint parse_##func(gchar *str, guint lng, parse_part *part, LSQScanfParse
         *pval = val;    \
         return ptr - str; \
     } \
-    for(ptr = str; g_ascii_isspace(*ptr); ++ptr);     \
+    for(ptr = str; g_ascii_isspace(*ptr); ++ptr) --lng; \
     ptr = g_strstr_len(ptr, lng, delim);    \
     if(NULL == ptr) return 0;   \
     val = g_ascii_strtoull(str, &ptr2, base);    \
@@ -626,7 +735,8 @@ parse_char (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+	LSQScanfParser *parser )
 {
     const gchar *ptr;
     gchar val;
@@ -688,7 +798,8 @@ parse_string (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+	LSQScanfParser *parser )
 {
     gchar *ptr;
     gchar *cur;
@@ -704,7 +815,14 @@ parse_string (
     if ( '\0' == delim[0] )
         return 0;
 
-    for ( cur = str; g_ascii_isspace( *cur ); ++cur );
+    for ( cur = str; g_ascii_isspace( *cur ); ++cur )
+    {
+        --lng;
+        if ( 0 == lng )
+        {
+            return 0;
+        }
+    }
 
     ptr = g_strstr_len(cur, lng, delim);
 
@@ -716,6 +834,59 @@ parse_string (
     return ptr - str;
 }
 
+static guint
+parse_datetime (
+        gchar *str,
+        guint lng,
+        parse_part *part,
+        LSQScanfParserContext *ctx,
+        LSQScanfParser *parser )
+{
+    gchar *ptr;
+    gchar *cur;
+    const gchar *delim;
+    LSQDateTime *pval;
+
+    if ( 0 == lng )
+    {
+        return 0;
+    }
+
+    delim = part->delimiter;
+    if ( ( NULL == delim ) && ( NULL == part->next ) )
+    {
+        delim = "\n";
+    }
+
+    for ( cur = str; g_ascii_isspace( *cur ); ++cur)
+    {
+    }
+
+    pval = &ctx->data_store[part->index_].dt;
+    ctx->props_store[part->index_] = pval;
+
+    *pval = lsq_datetime_from_string( cur, LSQ_PARSER(parser)->datetime_format, &ptr );
+    if ( LSQ_DATETIME_NULL == *pval )
+        return 0;
+
+    if ( ( ptr - str ) > lng )
+    {
+        return 0;
+    }
+
+    if ( '\0' == delim[0] )
+    {
+        lng -= ptr - str;
+        ptr = g_strstr_len ( ptr, lng, delim );
+        if ( NULL == ptr )
+        {
+            return 0;
+        }
+    }
+
+    return ptr - str;
+}
+
 DEF_PARSE_UNS(unsigned, 10, guint, guint, u)
 DEF_PARSE_UNS(unsigned16, 10, gushort, guint, u)
 DEF_PARSE_UNS(unsigned32, 10, gulong, gulong, ul)
@@ -731,7 +902,8 @@ parse_filename (
         gchar *str,
         guint lng,
         parse_part *part,
-        LSQScanfParserContext *ctx )
+        LSQScanfParserContext *ctx,
+	LSQScanfParser *parser )
 {
     gchar *ptr;
     const gchar *delim;
@@ -1124,7 +1296,7 @@ build_parser (
                     }
                 break;
                 /*}}}*/
-                /*{{{ floating point %d*/
+                /*{{{ floating point %f*/
                 case 'f':
                     g_return_if_fail( SIZE_NORMAL == size_flag || SIZE_LONGLONG == size_flag );
                     part->next = g_new0(parse_part, 1);
@@ -1208,6 +1380,25 @@ build_parser (
                     }
                 break;
                 /*}}}*/
+                /*{{{ datetime %t*/
+                case 't':
+                    g_return_if_fail(!size_flag);
+                    part->next = g_new0(parse_part, 1);
+                    part = part->next;
+                    part->width = width_flag;
+                    if(skip_flag)
+                    {
+                        part->function = skip_datetime;
+                    }
+                    else
+                    {
+                        part_count++;
+                        part->index_ = index_;
+                        part->function = parse_datetime;
+                        lsq_parser_set_property_type(LSQ_PARSER(parser), index_, LSQ_TYPE_DATETIME);
+                    }
+                break;
+                /*}}}*/
                 /*{{{ unsigned decimal %u*/
                 case 'u':
                     part->next = g_new0(parse_part, 1);
@@ -1327,7 +1518,7 @@ lsq_scanf_parser_parse (
         //parse
         if ( NULL != part->function )
         {
-            size = part->function(ptr, lng, part, ctx);
+            size = part->function(ptr, lng, part, ctx, parser);
             if ( 0 == size )
             {
                 //no match
diff --git a/libsqueeze/support-reader.c b/libsqueeze/support-reader.c
index 5032ec7..7430f62 100644
--- a/libsqueeze/support-reader.c
+++ b/libsqueeze/support-reader.c
@@ -138,6 +138,7 @@ lsq_support_reader_parse_file(const gchar *filename)
 	LSQParser *parser = NULL;
 	const gchar *parser_string;
 	const gchar *parser_regex;
+	const gchar *parser_datetime;
 	gchar **_mime_types;
 #ifdef HAVE_PCRE
 	gchar **regex_types;
@@ -202,6 +203,7 @@ lsq_support_reader_parse_file(const gchar *filename)
 	column_names = xfce_rc_read_list_entry(rc, "X-Squeeze-Headers", ";");
 	parser_string = xfce_rc_read_entry(rc, "X-Squeeze-Parse", NULL);
 	parser_regex = xfce_rc_read_entry(rc, "X-Squeeze-Parse-Regex", NULL);
+	parser_datetime = xfce_rc_read_entry(rc, "X-Squeeze-Parse-DateTime", NULL);
 
 	if (NULL != parser_string)
 	{
@@ -215,6 +217,10 @@ lsq_support_reader_parse_file(const gchar *filename)
 	    g_strfreev( regex_types );
 	}
 #endif
+        if ( NULL != parser_datetime )
+        {
+            lsq_parser_set_datetime_format( parser, parser_datetime );
+        }
 
 	_mime_types = mime_types;
 	for(i = 0; _mime_types[i]; ++i)
diff --git a/src/archive_store.c b/src/archive_store.c
index 8faed2e..03f8e74 100644
--- a/src/archive_store.c
+++ b/src/archive_store.c
@@ -867,7 +867,7 @@ sq_archive_entry_compare(SQArchiveStore *store, LSQArchiveIter *a, LSQArchiveIte
 		case G_TYPE_STRING:
 			if(g_value_get_string(&prop_a) == NULL)
 			{
-				retval = -1;
+				retval = ( NULL == g_value_get_string( &prop_b ) ) ? 0 : -1;
 				break;
 			}
 			if(g_value_get_string(&prop_b) == NULL)
@@ -891,6 +891,13 @@ sq_archive_entry_compare(SQArchiveStore *store, LSQArchiveIter *a, LSQArchiveIte
 		case G_TYPE_UINT:
 			retval = g_value_get_uint(&prop_a) - g_value_get_uint(&prop_b);
 			break;
+		default:
+			if ( LSQ_TYPE_DATETIME == lsq_archive_get_entry_property_type(archive, column) )
+                        {
+                            retval = lsq_datetime_cmp( g_value_get_datetime(&prop_a), g_value_get_datetime(&prop_b) );
+                            break;
+                        }
+			break;
 	}
 	g_value_unset(&prop_a);
 	g_value_unset(&prop_b);
diff --git a/src/notebook.c b/src/notebook.c
index de09a7c..2de6571 100644
--- a/src/notebook.c
+++ b/src/notebook.c
@@ -729,6 +729,14 @@ sq_notebook_treeview_reset_columns(LSQArchive *archive, GtkTreeView *treeview)
 		{
 			switch(lsq_archive_get_entry_property_type(archive, x))
 			{
+                                default:
+                                        if ( LSQ_TYPE_DATETIME != lsq_archive_get_entry_property_type(archive, x) )
+                                        {
+#ifdef DEBUG
+                                            g_debug("Should not be reached");
+#endif
+                                            continue;
+                                        }
         case(G_TYPE_CHAR):
 				case(G_TYPE_DOUBLE):
 				case(G_TYPE_FLOAT):
@@ -742,11 +750,6 @@ sq_notebook_treeview_reset_columns(LSQArchive *archive, GtkTreeView *treeview)
 					renderer = gtk_cell_renderer_text_new();
 					column = gtk_tree_view_column_new_with_attributes(lsq_archive_get_entry_property_name(archive, x), renderer, "text", x+SQ_ARCHIVE_STORE_EXTRA_PROP_COUNT, NULL);
 					break;
-        default:
-#ifdef DEBUG
-          g_debug("Should not be reached");
-#endif
-          continue;
 			}
 			gtk_tree_view_column_set_resizable(column, TRUE);
 			gtk_tree_view_column_set_sort_column_id(column, x+SQ_ARCHIVE_STORE_EXTRA_PROP_COUNT);


More information about the Xfce4-commits mailing list