自己手寫一個 VB 的 DateAdd 函式(VB/C 雙語言版本)
阿新 • • 發佈:2019-01-05
可能有些朋友覺得這是多餘的事情,既然 VB 有了 DateAdd 函式來進行日期運算,幹嘛還要自己手寫一個? 其實這一點也不多餘,因為有些時候我們的開發環境不一定就在 VB 裡,而那些個開發環境不一定就有那麼多現成的函式可以使用,那麼這個時候要做個日期運算那就不是那麼簡單的事情了。就比如我寫這函式的理由,就是在微控制器裡需要做日期運算寫的。因為在微控制器裡,就連想取得個時間都要外掛一個外圍的時鐘晶片,要讀個時間也要進行專門的通訊才能讀到內容,更別說什麼現成的日期時間型別或對其進行運算了,這些全要自己弄,所以做這些個蛋疼的事情並不是沒必要的,而是你是否接觸到這種蛋疼的需求而已。好了,閒話不多說,先看看這個函式如果用 VB 可以怎麼寫吧。
'==================================================================================================== ' Definition structure ( 結構體定義 ) '==================================================================================================== Private Type SYSTEMTIME wYear As Integer wMonth As Integer wDayOfWeek As Integer wDay As Integer wHour As Integer wMinute As Integer wSecond As Integer wMilliseconds As Integer End Type '==================================================================================================== ' API function declaration ( API 函式宣告 ) '==================================================================================================== Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, _ Source As Any, _ ByVal Length As Long) '==================================================================================================== ' Custom function ( 自定義函式 ) '==================================================================================================== '---------------------------------------------------------------------------------------------------- ' Function Name: DateAdd2 ' Description : A function for computing time. ' Input Parameter: interval - (String)Necessary,Type of operation time. ' : number - (Long)Necessary,The numeric value that needs to be performed. ' : dateInfo - (SYSTEMTIME)Necessary,The time required for computation is also ' : the result of computation.. ' Return Value: (void) - No return ' Version : 1.0.0 ' Author : Zhou Wen Xing <
[email protected]> ' CSDN Accounts: SupermanKing ' Date : June, 26nd 2018 '---------------------------------------------------------------------------------------------------- Private Sub DateAdd2(ByVal interval As String, _ ByVal number As Long, _ ByRef dateInfo As SYSTEMTIME) Dim m_Year As Long Dim IsLeapYear As Long Dim m_Month As Long Dim m_AllMonth As Long Dim m_Day As Long Dim m_AllDay As Long Dim m_DayCount As Long Dim m_AllHour As Long Dim m_Hour As Long Dim m_AllMinute As Long Dim m_Minute As Long Dim m_AllSecond As Long Dim m_Second As Long Dim m_SYSTEMTIME As SYSTEMTIME Select Case interval Case "yyyy": dateInfo.wYear = dateInfo.wYear + number Case "m" m_Year = dateInfo.wYear m_AllMonth = dateInfo.wMonth + number If m_AllMonth > 12 Then m_Year = m_Year + Int(m_AllMonth / 12) m_Month = m_AllMonth Mod 12 If m_Month = 0 Then dateInfo.wMonth = 1 Else dateInfo.wMonth = m_Month End If dateInfo.wYear = m_Year Else dateInfo.wMonth = m_AllMonth End If Case "d" m_Year = dateInfo.wYear If (m_Year - 1980) Mod 4 = 0 Then IsLeapYear = 1 Else IsLeapYear = 0 End If m_Month = dateInfo.wMonth Select Case m_Month Case 1, 3, 5, 7, 8, 10, 12 m_DayCount = 31 Case 2 If IsLeapYear Then m_DayCount = 29 Else m_DayCount = 28 End If Case 4, 6, 9, 11 m_DayCount = 30 End Select m_AllDay = dateInfo.wDay + number If m_AllDay > m_DayCount Then Do m_AllDay = m_AllDay - m_DayCount m_Month = m_Month + 1 If m_AllDay > m_DayCount Then If m_Month > 12 Then m_Month = 1 m_Year = m_Year + 1 If (m_Year - 1980) Mod 4 = 0 Then IsLeapYear = 1 Else IsLeapYear = 0 End If End If End If Select Case m_Month Case 1, 3, 5, 7, 8, 10, 12 m_DayCount = 31 Case 2 If IsLeapYear Then m_DayCount = 29 Else m_DayCount = 28 End If Case 4, 6, 9, 11 m_DayCount = 30 End Select Loop While m_AllDay > m_DayCount If m_AllDay = 0 Then m_AllDay = 1 End If dateInfo.wDay = m_AllDay dateInfo.wMonth = m_Month dateInfo.wYear = m_Year Else dateInfo.wDay = m_AllDay End If Case "h" m_AllHour = dateInfo.wHour + number If m_AllHour < 24 Then dateInfo.wHour = m_AllHour Else m_Hour = m_AllHour Mod 24 m_AllDay = Int(m_AllHour / 24) CopyMemory m_SYSTEMTIME, dateInfo, LenB(m_SYSTEMTIME) DateAdd2 "d", CInt(m_AllDay), m_SYSTEMTIME dateInfo.wHour = m_Hour dateInfo.wDay = m_SYSTEMTIME.wDay dateInfo.wMonth = m_SYSTEMTIME.wMonth dateInfo.wYear = m_SYSTEMTIME.wYear End If Case "n" m_AllMinute = dateInfo.wMinute + number If m_AllMinute < 60 Then dateInfo.wMinute = m_AllMinute Else m_Minute = m_AllMinute Mod 60 m_AllHour = Int(m_AllMinute / 60) CopyMemory m_SYSTEMTIME, dateInfo, LenB(m_SYSTEMTIME) DateAdd2 "h", CInt(m_AllHour), m_SYSTEMTIME dateInfo.wMinute = m_Minute dateInfo.wHour = m_SYSTEMTIME.wHour dateInfo.wDay = m_SYSTEMTIME.wDay dateInfo.wMonth = m_SYSTEMTIME.wMonth dateInfo.wYear = m_SYSTEMTIME.wYear End If Case "s" m_AllSecond = dateInfo.wSecond + number If m_AllSecond < 60 Then dateInfo.wSecond = m_AllSecond Else m_Second = m_AllSecond Mod 60 m_AllMinute = Int(m_AllSecond / 60) CopyMemory m_SYSTEMTIME, dateInfo, LenB(m_SYSTEMTIME) DateAdd2 "n", CInt(m_AllMinute), m_SYSTEMTIME dateInfo.wSecond = m_Second dateInfo.wMinute = m_SYSTEMTIME.wMinute dateInfo.wHour = m_SYSTEMTIME.wHour dateInfo.wDay = m_SYSTEMTIME.wDay dateInfo.wMonth = m_SYSTEMTIME.wMonth dateInfo.wYear = m_SYSTEMTIME.wYear End If End Select End Sub
上面是 VB 的實現過程,我寫來主要是用來除錯邏輯的 ,因為如果要在微控制器裡除錯邏輯怎麼都沒直接在 Windows 下方便 ,其實寫好了程式直接翻譯一下就可以成為 C 語言的函數了,比如以下程式碼:
//====================================================================================================
// Adduction head file ( 引用標頭檔案 )
//====================================================================================================
#include <STRING.H>
//====================================================================================================
// Type definition ( 型別定義 )
//====================================================================================================
#define BYTE unsigned char
#define WORD unsigned int
//====================================================================================================
// Definition structure ( 結構體定義 )
//====================================================================================================
typedef struct tagSYSTEMTIME{
BYTE Century; // 世紀
BYTE FullYear; // 年份
BYTE Month; // 月份
BYTE Day; // 日期
BYTE Hours; // 小時
BYTE Minutes; // 分鐘
BYTE Seconds; // 秒鐘
BYTE Week; // 周幾
}SYSTEMTIME,*PSYSTEMTIME;
//====================================================================================================
// Custom function ( 自定義函式 )
//====================================================================================================
//----------------------------------------------------------------------------------------------------
// Function Name: DateAdd
// Description : A function for computing time.
// Input Parameter: interval - (char *)Necessary,Type of operation time.
// : number - (WORD)Necessary,The numeric value that needs to be performed.
// : dateInfo - (SYSTEMTIME *)Necessary,The time required for computation is also
// : the result of computation..
// Return Value: (void) - No return
// Version : 1.0.0
// Author : Zhou Wen Xing <[email protected]>
// CSDN Accounts: SupermanKing
// Date : June, 26nd 2018
//----------------------------------------------------------------------------------------------------
void DateAdd(char *interval,WORD number,SYSTEMTIME *dateInfo)
{
WORD m_Year;
WORD m_Month;
WORD m_Hour;
WORD m_Minute;
WORD m_Second;
WORD m_AllMonth;
WORD m_AllDay;
WORD m_AllHour;
WORD m_AllMinute;
WORD m_AllSecond;
WORD m_DayCount;
BYTE IsLeapYear;
BYTE m_SType;
SYSTEMTIME m_SYSTEMTIME;
if(strcmp(interval,"y")){
m_SType = 0;
}else if(strcmp(interval,"M")){
m_SType = 1;
}else if(strcmp(interval,"d")){
m_SType = 2;
}else if(strcmp(interval,"h")){
m_SType = 3;
}else if(strcmp(interval,"i")){
m_SType = 4;
}else if(strcmp(interval,"s")){
m_SType = 5;
}
switch(m_SType){
case 0: // 年份計算
m_Year = (dateInfo->Century*100)+dateInfo->FullYear;
m_Year += number;
dateInfo->Century = ((m_Year-(m_Year%100))/100)&0xFF;
dateInfo->FullYear = (m_Year%100)&0xFF;
break;
case 1: // 月份計算
m_Year = (dateInfo->Century*100)+dateInfo->FullYear;
m_AllMonth = dateInfo->Month+number;
if(m_AllMonth>12){
m_Year = m_Year+(m_AllMonth / 12);
m_Month = m_AllMonth % 12;
if(m_Month==0){
dateInfo->Month = 1;
}else{
dateInfo->Month = m_Month;
}
dateInfo->Century = ((m_Year-(m_Year%100))/100)&0xFF;
dateInfo->FullYear = (m_Year%100)&0xFF;
}else{
dateInfo->Month = m_AllMonth;
}
break;
case 2: // 日期計算
m_Year = (dateInfo->Century*100)+dateInfo->FullYear;
if((m_Year-1980)%4==0){
IsLeapYear = 1;
}else{
IsLeapYear = 0;
}
m_Month = dateInfo->Month;
switch(m_Month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
m_DayCount = 31;
break;
case 2:
if(IsLeapYear){
m_DayCount = 29;
}else{
m_DayCount = 28;
}
break;
case 4:
case 6:
case 9:
case 11:
m_DayCount = 30;
break;
}
m_AllDay = dateInfo->Day+number;
if(m_AllDay>m_DayCount){
while(m_AllDay>m_DayCount){
m_AllDay = m_AllDay - m_DayCount;
m_Month++;
if(m_AllDay>m_DayCount){
if(m_Month>12){
m_Month = 1;
m_Year++;
if((m_Year-1980)%4==0){
IsLeapYear = 1;
}else{
IsLeapYear = 0;
}
}
}
switch(m_Month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
m_DayCount = 31;
break;
case 2:
if(IsLeapYear){
m_DayCount = 29;
}else{
m_DayCount = 28;
}
break;
case 4:
case 6:
case 9:
case 11:
m_DayCount = 30;
break;
}
}
if(m_AllDay == 0){
m_AllDay = 1;
}
dateInfo->Day = m_AllDay&0xFF;
dateInfo->Month = m_Month&0xFF;
dateInfo->Century = ((m_Year-(m_Year%100))/100)&0xFF;
dateInfo->FullYear = (m_Year%100)&0xFF;
}else{
dateInfo->Day = m_AllDay&0xFF;
}
break;
case 3: // 小時計算
m_AllHour = dateInfo->Hours + number;
if(m_AllHour<24){
dateInfo->Hours = m_AllHour&0xFF;
}else{
m_Hour = m_AllHour%24;
m_AllDay = m_AllHour/24;
memcpy((void *)&m_SYSTEMTIME,(void *)dateInfo,sizeof(SYSTEMTIME));
DateAdd("d",m_AllDay,(SYSTEMTIME *)&m_SYSTEMTIME);
dateInfo->Hours = m_Hour&0xFF;
dateInfo->Day = m_SYSTEMTIME.Day;
dateInfo->Month = m_SYSTEMTIME.Month;
dateInfo->FullYear = m_SYSTEMTIME.FullYear;
dateInfo->Century = m_SYSTEMTIME.Century;
}
break;
case 4: // 分鐘計算
m_AllMinute = dateInfo->Minutes + number;
if(m_AllMinute<60){
dateInfo->Minutes = m_AllMinute&0xFF;
}else{
m_Minute = m_AllMinute%60;
m_AllHour = m_Minute/60;
memcpy((void *)&m_SYSTEMTIME,(void *)dateInfo,sizeof(SYSTEMTIME));
DateAdd("h",m_AllHour,(SYSTEMTIME *)&m_SYSTEMTIME);
dateInfo->Minutes = m_Minute&0xFF;
dateInfo->Hours = m_SYSTEMTIME.Hours;
dateInfo->Day = m_SYSTEMTIME.Day;
dateInfo->Month = m_SYSTEMTIME.Month;
dateInfo->FullYear = m_SYSTEMTIME.FullYear;
dateInfo->Century = m_SYSTEMTIME.Century;
}
break;
case 5: // 秒鐘計算
m_AllSecond = dateInfo->Seconds + number;
if(m_AllSecond<60){
dateInfo->Seconds = m_AllSecond&0xFF;
}else{
m_Second = m_AllSecond%60;
m_AllMinute = m_AllSecond/60;
memcpy((void *)&m_SYSTEMTIME,(void *)dateInfo,sizeof(SYSTEMTIME));
DateAdd("n",m_AllMinute,(SYSTEMTIME *)&m_SYSTEMTIME);
dateInfo->Seconds = m_Second&0xFF;
dateInfo->Minutes = m_SYSTEMTIME.Minutes;
dateInfo->Hours = m_SYSTEMTIME.Hours;
dateInfo->Day = m_SYSTEMTIME.Day;
dateInfo->Month = m_SYSTEMTIME.Month;
dateInfo->FullYear = m_SYSTEMTIME.FullYear;
dateInfo->Century = m_SYSTEMTIME.Century;
}
break;
}
}
程式碼看上去是不是就像直譯的,其實本來也是差不多直譯過來用的。好了有需要的就拿去用