This repository has been archived on 2023-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
bl_mcu_sdk/common/timestamp/timestamp.c

138 lines
4.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file timestamp.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "timestamp.h"
#include "misc.h"
#define FOUR_YEAR_DAY ((365 << 2) + 1) //The total number of days in a 4-year cycle
#define TIMEZONE (8) //Beijing time Zone adjustment
#define SEC_NUM_PER_DAY (24 * 60 * 60)
#define SEC_NUM_PER_HOUR (60 * 60)
#define SEC_NUM_PER_MINUTE (60)
static uint8_t month_day[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //平年
static uint8_t Leap_month_day[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //闰年
/**
* @bref judge if it is a leap year
* @para year to be judge
* @return 1leap year 0 nonleap year
*/
bool check_leap_year(uint16_t year)
{
if (year % 4) {
return false;
} else {
if ((year % 100 == 0) && (year % 400 != 0)) {
return false;
} else {
return true;
}
}
}
void cal_weekday(rtc_time *beijing_time)
{
uint32_t y,m,d,w;
y=beijing_time->year;
m=beijing_time->month;
d=beijing_time->day;
if((m==1)||(m==2))
{
m+=12;
y--;
}
/*
把一月和二月看成是上一年的十三月和十四月如果是2004-1-10则换算成2003-13-10来代入公式计算。
以公元元年为参考公元元年1月1日为星期一</PRE><PRE>程序如下:
利用基姆拉尔森计算日期公式 w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)
*/
w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
beijing_time->week=(uint8_t)w;
}
void unixtime2bejingtime(uint32_t unixtime, rtc_time *beijing_time)
{
uint32_t totle_day_num;
uint32_t current_sec_num;
uint16_t remain_day;
uint16_t temp_year;
uint8_t *p = NULL;
totle_day_num = unixtime / SEC_NUM_PER_DAY; //The total number of days
current_sec_num = unixtime % SEC_NUM_PER_DAY; //The number of seconds this day
/* use the number of seconds this day, To calculate hour\minute\second */
beijing_time->hour = current_sec_num / SEC_NUM_PER_HOUR;
beijing_time->minute = (current_sec_num % SEC_NUM_PER_HOUR) / SEC_NUM_PER_MINUTE;
beijing_time->second = (current_sec_num % SEC_NUM_PER_HOUR) % SEC_NUM_PER_MINUTE;
/* Adjust the time zone and check whether the date is +1 */
beijing_time->hour += 8;
if (beijing_time->hour > 23) {
beijing_time->hour -= 24;
totle_day_num++;
}
/* calculate year */
beijing_time->year = 1970 + (totle_day_num / FOUR_YEAR_DAY) * 4; // 4-year as a cycle
remain_day = totle_day_num % FOUR_YEAR_DAY; //remaining day nym( < 4 year )
/* calculate year & day */
temp_year = check_leap_year(beijing_time->year) ? 366 : 365;
while (remain_day >= temp_year) {
beijing_time->year++;
remain_day -= temp_year;
temp_year = check_leap_year(beijing_time->year) ? 366 : 365;
}
/* Calculate specific dates(month\day)*/
p = check_leap_year(beijing_time->year) ? Leap_month_day : month_day;
remain_day++; //The actual day starts at 1
beijing_time->month = 0;
while (remain_day > *(p + beijing_time->month)) {
remain_day -= *(p + beijing_time->month);
beijing_time->month++;
}
beijing_time->month++; //The actual month starts at 1
beijing_time->day = remain_day;
/*利用基姆拉尔森计算日期公式 w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)*/
beijing_time->week = beijing_time->day + 2*beijing_time->month + 3*(beijing_time->month+1)/5 + \
beijing_time->year + beijing_time->year/4 - beijing_time->year/100 +beijing_time->year/400 ;
cal_weekday(beijing_time);
}