mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-14 05:58:13 +08:00
231 lines
7.6 KiB
C
231 lines
7.6 KiB
C
/**
|
|
******************************************************************************
|
|
* @file mico_system_time.c
|
|
* @author William Xu
|
|
* @version V1.0.0
|
|
* @date 22-Aug-2016
|
|
* @brief This file provide the time functions from MiCO system.
|
|
******************************************************************************
|
|
*
|
|
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
|
* Copyright (c) 2016 MXCHIP Inc.
|
|
*
|
|
* The contents of this file may not be disclosed to third parties, copied or
|
|
* duplicated in any form, in whole or in part, without the prior written
|
|
* permission of MXCHIP Corporation.
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** @file
|
|
*
|
|
*/
|
|
|
|
#include "mico_system.h"
|
|
#include "StringUtils.h"
|
|
#include "string.h"
|
|
|
|
/******************************************************
|
|
* Macros
|
|
******************************************************/
|
|
|
|
#define UTC_TIME_TO_TIME( utc_time ) ( utc_time / 1000 )
|
|
#define BASE_UTC_YEAR (1970)
|
|
#define IS_LEAP_YEAR( year ) ( ( ( year ) % 400 == 0 ) || \
|
|
( ( ( year ) % 100 != 0 ) && ( ( year ) % 4 == 0 ) ) )
|
|
|
|
/******************************************************
|
|
* Constants
|
|
******************************************************/
|
|
|
|
#define SECONDS_IN_365_DAY_YEAR (31536000)
|
|
#define SECONDS_IN_A_DAY (86400)
|
|
#define SECONDS_IN_A_HOUR (3600)
|
|
#define SECONDS_IN_A_MINUTE (60)
|
|
static const uint32_t secondsPerMonth[ 12 ] =
|
|
{
|
|
31*SECONDS_IN_A_DAY,
|
|
28*SECONDS_IN_A_DAY,
|
|
31*SECONDS_IN_A_DAY,
|
|
30*SECONDS_IN_A_DAY,
|
|
31*SECONDS_IN_A_DAY,
|
|
30*SECONDS_IN_A_DAY,
|
|
31*SECONDS_IN_A_DAY,
|
|
31*SECONDS_IN_A_DAY,
|
|
30*SECONDS_IN_A_DAY,
|
|
31*SECONDS_IN_A_DAY,
|
|
30*SECONDS_IN_A_DAY,
|
|
31*SECONDS_IN_A_DAY,
|
|
};
|
|
|
|
/******************************************************
|
|
* Enumerations
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Type Definitions
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Structures
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Static Function Declarations
|
|
******************************************************/
|
|
|
|
/******************************************************
|
|
* Variable Definitions
|
|
******************************************************/
|
|
|
|
static mico_utc_time_ms_t current_utc_time = 0;
|
|
static mico_time_t last_utc_time_mico_reference = 0;
|
|
|
|
/******************************************************
|
|
* Function Definitions
|
|
******************************************************/
|
|
|
|
OSStatus mico_time_get_utc_time( mico_utc_time_t* utc_time )
|
|
{
|
|
mico_utc_time_ms_t utc_time_ms;
|
|
|
|
mico_time_get_utc_time_ms( &utc_time_ms );
|
|
|
|
*utc_time = (uint32_t)( utc_time_ms / 1000 );
|
|
return kNoErr;
|
|
}
|
|
|
|
OSStatus mico_time_get_utc_time_ms( mico_utc_time_ms_t* utc_time_ms )
|
|
{
|
|
mico_time_t temp_mico_time;
|
|
uint32_t time_since_last_reference;
|
|
|
|
/* Update the UTC time by the time difference between now and the last update */
|
|
mico_time_get_time( &temp_mico_time );
|
|
time_since_last_reference = ( temp_mico_time - last_utc_time_mico_reference );
|
|
|
|
if ( time_since_last_reference != 0 )
|
|
{
|
|
current_utc_time += time_since_last_reference;
|
|
last_utc_time_mico_reference = temp_mico_time;
|
|
}
|
|
|
|
*utc_time_ms = current_utc_time;
|
|
return kNoErr;
|
|
}
|
|
|
|
OSStatus mico_time_set_utc_time_ms( const mico_utc_time_ms_t* utc_time_ms )
|
|
{
|
|
mico_time_get_time( &last_utc_time_mico_reference );
|
|
current_utc_time = *utc_time_ms;
|
|
return kNoErr;
|
|
}
|
|
|
|
|
|
OSStatus mico_time_get_iso8601_time(iso8601_time_t* iso8601_time)
|
|
{
|
|
mico_utc_time_ms_t utc_time_ms;
|
|
|
|
mico_time_get_utc_time_ms( &utc_time_ms );
|
|
return mico_time_convert_utc_ms_to_iso8601( utc_time_ms, iso8601_time );
|
|
}
|
|
|
|
OSStatus mico_time_convert_utc_ms_to_iso8601( mico_utc_time_ms_t utc_time_ms, iso8601_time_t* iso8601_time )
|
|
{
|
|
uint32_t a;
|
|
uint16_t year;
|
|
uint16_t number_of_leap_years;
|
|
uint8_t month;
|
|
uint8_t day;
|
|
uint8_t hour;
|
|
uint8_t minute;
|
|
uint64_t second;
|
|
uint16_t sub_second;
|
|
mico_bool_t is_a_leap_year;
|
|
|
|
second = utc_time_ms / 1000; /* Time is in milliseconds. Convert to seconds */
|
|
sub_second = (uint16_t) ( ( utc_time_ms % 1000 ) * 1000 ); /* Sub-second is in microseconds */
|
|
|
|
/* Calculate year */
|
|
year = (uint16_t)( BASE_UTC_YEAR + second / SECONDS_IN_365_DAY_YEAR );
|
|
number_of_leap_years = ( uint16_t )( ( ( year - ( BASE_UTC_YEAR - ( BASE_UTC_YEAR % 4 ) + 1 ) ) / 4 ) -
|
|
( ( year - ( BASE_UTC_YEAR - ( BASE_UTC_YEAR % 100 ) + 1 ) ) / 100 ) +
|
|
( ( year - ( BASE_UTC_YEAR - ( BASE_UTC_YEAR % 400 ) + 1 ) ) / 400 ) );
|
|
second -= (uint64_t)( (uint64_t)( year - BASE_UTC_YEAR ) * SECONDS_IN_365_DAY_YEAR );
|
|
|
|
if ( second >= ( uint64_t )( number_of_leap_years * SECONDS_IN_A_DAY ) )
|
|
{
|
|
second -= (uint64_t) ( ( number_of_leap_years * SECONDS_IN_A_DAY ) );
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
second += SECONDS_IN_365_DAY_YEAR;
|
|
year--;
|
|
if ( IS_LEAP_YEAR( year ) )
|
|
{
|
|
second += SECONDS_IN_A_DAY;
|
|
}
|
|
} while ( second < ( uint64_t )( number_of_leap_years * SECONDS_IN_A_DAY ) );
|
|
|
|
second -= ( uint64_t )( number_of_leap_years * SECONDS_IN_A_DAY );
|
|
}
|
|
|
|
/* Remember if the current year is a leap year */
|
|
is_a_leap_year = ( IS_LEAP_YEAR( year ) ) ? MICO_TRUE : MICO_FALSE;
|
|
|
|
/* Calculate month */
|
|
month = 1;
|
|
|
|
for ( a = 0; a < 12; ++a )
|
|
{
|
|
uint32_t seconds_per_month = secondsPerMonth[a];
|
|
/* Compensate for leap year */
|
|
if ( ( a == 1 ) && is_a_leap_year )
|
|
{
|
|
seconds_per_month += SECONDS_IN_A_DAY;
|
|
}
|
|
if ( second >= seconds_per_month )
|
|
{
|
|
second -= seconds_per_month;
|
|
month++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Calculate day */
|
|
day = (uint8_t) ( second / SECONDS_IN_A_DAY );
|
|
second -= (uint64_t) ( day * SECONDS_IN_A_DAY );
|
|
++day;
|
|
|
|
/* Calculate hour */
|
|
hour = (uint8_t) ( second / SECONDS_IN_A_HOUR );
|
|
second -= (uint64_t) ( hour * SECONDS_IN_A_HOUR );
|
|
|
|
/* Calculate minute */
|
|
minute = (uint8_t) ( second / SECONDS_IN_A_MINUTE );
|
|
second -= (uint64_t) ( minute * SECONDS_IN_A_MINUTE );
|
|
|
|
/* Write iso8601 time (Note terminating nulls get overwritten intentionally) */
|
|
unsigned_to_decimal_string( year, iso8601_time->year, 4, 4 );
|
|
unsigned_to_decimal_string( month, iso8601_time->month, 2, 2 );
|
|
unsigned_to_decimal_string( day, iso8601_time->day, 2, 2 );
|
|
unsigned_to_decimal_string( hour, iso8601_time->hour, 2, 2 );
|
|
unsigned_to_decimal_string( minute, iso8601_time->minute, 2, 2 );
|
|
unsigned_to_decimal_string( (uint8_t)second, iso8601_time->second, 2, 2 );
|
|
unsigned_to_decimal_string( sub_second, iso8601_time->sub_second, 6, 6 );
|
|
|
|
iso8601_time->T = 'T';
|
|
iso8601_time->Z = 'Z';
|
|
iso8601_time->colon1 = ':';
|
|
iso8601_time->colon2 = ':';
|
|
iso8601_time->dash1 = '-';
|
|
iso8601_time->dash2 = '-';
|
|
iso8601_time->decimal = '.';
|
|
|
|
return kNoErr;
|
|
}
|