
/*----------------------------------------------------------------------+
 |                                                                      |
 |      wtime.h -- definition of wtime type and functions               |
 |                                                                      |
 +----------------------------------------------------------------------*/

/*
 *  Author:
 *      Marcel van Kervinck
 *
 *  Creation date:
 *      2006-12-26
 *
 *  Description:
 *      Wtime is a signed 64-bit timestamp with over 8000 year span and
 *      microsecond resolution. 'Wtime' means 'wide time', 'world time'
 *      and/or 'wall time'. It represents civil time, or wall clock time,
 *      in a compact binary encoding while preserving both the relation to
 *      UTC and the local time. It is therefore suited for use in binary
 *      file formats (eg. log files), file systems and Internet messages.
 *      For many purposes, universal time and original local time can both
 *      be important later, depending on the reader's particular need.
 *
 *  History:
 *      2006-12-26 (marcelk) First version for Mac and Linux.
 *      2007-06-20 (marcelk) Prepare minimal version for use in projects.
 *                           Removed incomplete functions for future redesign.
 *      2007-06-27 (marcelk) Documented wtime_t layout.
 */

/*----------------------------------------------------------------------+
 |      Copyright                                                       |
 +----------------------------------------------------------------------*/

/*
 *  Copyright (C) 2006-2007, Marcel van Kervinck
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *  3. Neither the name of the copyright holder nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 *  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef WTIME_H
#define WTIME_H

/*----------------------------------------------------------------------+
 |      Definitions: errors                                             |
 +----------------------------------------------------------------------*/

#ifdef WTIME_BASE_H

/*
 *  Compiled with fake base.h
 */
#ifndef WTIME_ERR_BASE
#define WTIME_ERR_BASE (('w' << 24) | ('t' << 16))
#endif

#define WTIME_ERR_SYSTEM                (WTIME_ERR_BASE + 0x0000)
#define WTIME_ERR_BUFFER_TOO_SMALL      (WTIME_ERR_BASE + 0x0001)

#define WTIME_ERR_MAX (WTIME_ERR_BASE + 0x0001)

#else /* !defined(WTIME_BASE_H) */

/*
 *  Compiled with real base.h
 */
#define WTIME_ERR_BUFFER_TOO_SMALL (ERR_BUFFER_TOO_SMALL)

#endif

/*----------------------------------------------------------------------+
 |      Type: wtime_t                                                   |
 +----------------------------------------------------------------------*/

/*
 *  wtime_t type definition: 64-bit signed integer
 */
typedef signed long long wtime_t;

/*----------------------------------------------------------------------+
 |      Type: enum wtime_zone                                           |
 +----------------------------------------------------------------------*/

enum wtime_zone {
        wtime_zone_invalid = 0,

        /* all half-hour time zones */

        /* west of UTC */
        wtime_zone_w1200,
        wtime_zone_w1130,
        wtime_zone_w1100,
        wtime_zone_w1030,
        wtime_zone_w1000,
        wtime_zone_w0930,
        wtime_zone_w0900,
        wtime_zone_w0830,
        wtime_zone_w0800,
        wtime_zone_w0730,
        wtime_zone_w0700,
        wtime_zone_w0630,
        wtime_zone_w0600,
        wtime_zone_w0530,
        wtime_zone_w0500,
        wtime_zone_w0430,
        wtime_zone_w0400,
        wtime_zone_w0330,
        wtime_zone_w0300,
        wtime_zone_w0230,
        wtime_zone_w0200,
        wtime_zone_w0130,
        wtime_zone_w0100,
        wtime_zone_w0030,

        /* UTC */
        wtime_zone_z0000, /* London */

        /* east of UTC */
        wtime_zone_e0030,
        wtime_zone_e0100, /* Amsterdam */
        wtime_zone_e0130,
        wtime_zone_e0200,
        wtime_zone_e0230,
        wtime_zone_e0300,
        wtime_zone_e0330,
        wtime_zone_e0400,
        wtime_zone_e0430,
        wtime_zone_e0500,
        wtime_zone_e0530,
        wtime_zone_e0630,
        wtime_zone_e0600,
        wtime_zone_e0700,
        wtime_zone_e0730,
        wtime_zone_e0800, /* Taipei */
        wtime_zone_e0830,
        wtime_zone_e0900, /* Tokyo */
        wtime_zone_e0930,
        wtime_zone_e1000,
        wtime_zone_e1030,
        wtime_zone_e1100,
        wtime_zone_e1130,
        wtime_zone_e1200,

        /* special administrative time zones */
        wtime_zone_e1300x,
        wtime_zone_e1400x,
        wtime_zone_e0545x, /* Kathmandu */
        wtime_zone_e0845x,
        wtime_zone_e1245x,

        /* reserved for extensions */
        wtime_zone_reserved_55,
        wtime_zone_reserved_56,
        wtime_zone_reserved_57,
        wtime_zone_reserved_58,
        wtime_zone_reserved_59,
        wtime_zone_reserved_60,

        /* solar time systems */
        wtime_zone_solar_west, /* ...1023 : 1-minute steps westwards */
        wtime_zone_solar_east, /* 0...    : 1-minute steps eastwards */

        wtime_zone_unknown_local,
};

/*----------------------------------------------------------------------+
 |      Function: wtime_init                                            |
 +----------------------------------------------------------------------*/

err_t wtime_init(void);

/*----------------------------------------------------------------------+
 |      Function: wtime_get_current                                     |
 +----------------------------------------------------------------------*/

err_t wtime_get_current(wtime_t *current);

/*----------------------------------------------------------------------+
 |      Function: wtime_to_string                                       |
 +----------------------------------------------------------------------*/

#define WTIME_STRING_LEN_MAX (sizeof "-YYYY-mm-dd HH:MM:SS.uuuuuu +zzzz" - 1)

/* @TODO: write in a byte buffer using a cursor */
err_t
wtime_to_string(
        char *buf,
        int size,
        wtime_t time);

/*----------------------------------------------------------------------+
 |      Other functions (not implemented yet)                           |
 +----------------------------------------------------------------------*/

#ifdef CLOCKS_PER_SEC /* time_t exists and is included */

err_t wtime_posix_from_time_t(
        wtime_t *time,
        time_t clock,
        long zone,
        int leaps); /* unknown, automatic, value */

err_t wtime_posix_to_time_t(
        wtime_t *time,
        time_t clock,
        long zone);

err_t wtime_posix_from_struct_tm(
        wtime_t *time,
        const struct tm *tm);

err_t wtime_posix_to_struct_tm(
        wtime_t *time,
        const struct tm *tm);

#endif /* CLOCKS_PER_SEC */

err_t wtime_is_valid(
        wtime_t timestamp,
        bool *is_valid,
        err_t *reason);

err_t wtime_from_string(
        wtime_t *time,
        const char *buf,
        int *size);

err_t wtime_diff(
        double *diff,
        wtime_t t1,
        wtime_t t0);

err_t wtime_diff_micros(
        long long *diff_micros,
        wtime_t t1,
        wtime_t t0);

err_t wtime_add_micros(
        wtime_t *result,
        wtime_t time,
        long long micros);

err_t wtime_add_seconds(
        wtime_t *result,
        wtime_t time,
        double seconds);

err_t wtime_add_days(
        wtime_t *result,
        wtime_t time,
        double days);

/*----------------------------------------------------------------------+
 |                                                                      |
 +----------------------------------------------------------------------*/

#endif /* WTIME_H */


