138 lines
4.3 KiB
C
138 lines
4.3 KiB
C
|
/**
|
|||
|
* @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 1:leap 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);
|
|||
|
}
|