如何调用 SMALLSO Public API 获取时间戳

in 开源 with 2 comments

0x01 前言

关注 SMALLSO 的开发人员或许都知道 SMALLSO 提供了在线时间戳 Public API,供个人或企业开发者免费调用。但之前提供的旧版本仅限于获取北京时间的 10 位时间戳,在功能上有所缺失且没有 Demo。为了完善这一 Public API,这次提供了全新的 GetCurrentTime Public API 供个人或企业开发者使用。

0x02 描述

接口描述

输入参数

参数名称 必选 类型 描述
type String 获取的时间类型(cut,time)
format String 输出的时间格式(例如:yyyy/MM/dd)
utc Boolean 是否输出 UTC 时间,若为 false 则输出北京时间

参数取值

0x03 示例

如何获取 UTC 时间戳?

输入

https://api.xiaoyy.org/public/v1/GetCurrentTime?type=cut
&utc=true

输出

1532321286

如何获取默认 UTC 时间格式化字符串?

输入

https://api.xiaoyy.org/public/v1/GetCurrentTime?type=time
&utc=true

输出

2018/7/23 4:49:23

如何获取指定 UTC 时间格式化字符串?

输入

https://api.xiaoyy.org/public/v1/GetCurrentTime?type=time
&utc=true
&format=yyyy-MM-dd H:mm:ss

输出

2018-07-23 4:57:28

0x04 VC Demo

您无需复制,下方会提供完整的 VC 及 VC# Demo 下载。

头文件(ontime.h)

#pragma once

/* Contains C Standard Library header files */
#include <time.h>

/* Contains the necessary Windows SDK header files */
#include "windows.h"

/* Define the API call URL for SMALLSO Time Server */
#ifdef _UNICODE
    #define INTERNET_API_URL L"https://api.xiaoyy.org/public/v1/GetCurrentTime?utc=true"
#else
    #define INTERNET_API_URL "https://api.xiaoyy.org/public/v1/GetCurrentTime?utc=true"
#endif

/* Define the required macro */
#define INVALID_TIMECUT 0

/* Function that defines the output */
BOOL 
TimecutToSystemTime(
    _In_            time_t                      tCurrentTimecut,
    _Out_       LPSYSTEMTIME        lpSystemTime,
    _In_            BOOL                        bLocalTime
);

time_t 
GetInternetUtcTimecut(
    VOID
);

源文件(ontime.cpp)

#include "stdafx.h"
#include "ontime.h"
#include <time.h>
#include "windows.h"
#include "wininet.h"

/* Static link wininet static library */
#pragma comment(lib,"wininet.lib")

/* Convert UNIX time truncation to Windows SYSTEMTIME time structure */
BOOL TimecutToSystemTime(time_t tCurrentTimecut, LPSYSTEMTIME lpSystemTime, BOOL bLocalTime)
{
    BOOL bResult = FALSE;
    if (tCurrentTimecut && lpSystemTime)
    {
        errno_t eResult = NULL;
        tm obStanTime = { NULL };
        if (bLocalTime)
            eResult = localtime_s(&obStanTime, &tCurrentTimecut);
        else
            eResult = gmtime_s(&obStanTime, &tCurrentTimecut);
        if (eResult == 0)
        {
            lpSystemTime->wYear = 1900 + obStanTime.tm_year;
            lpSystemTime->wMonth = 1 + obStanTime.tm_mon;
            lpSystemTime->wDay = obStanTime.tm_mday;
            lpSystemTime->wDayOfWeek = obStanTime.tm_wday;
            lpSystemTime->wHour = obStanTime.tm_hour;
            lpSystemTime->wMinute = obStanTime.tm_min;
            lpSystemTime->wSecond = obStanTime.tm_sec;
            bResult = TRUE;
        }
    }
    return bResult;
}

/* UTF8 decoding routine () */
BOOL InternetCharToUnicode(LPCSTR lpcInternetChar, DWORD dwCharNumberOfByte,
    LPWSTR lpUnicodeBuffer, LPDWORD lpBufferNumberOfByte)
{
    BOOL bResult = FALSE;
    if (lpcInternetChar && lpUnicodeBuffer && lpBufferNumberOfByte)
    {
        DWORD dwNeedSize = MultiByteToWideChar(CP_UTF8, NULL, lpcInternetChar, dwCharNumberOfByte, NULL, NULL);
        if (*lpBufferNumberOfByte >= dwNeedSize) // buffer size verification
        {
            DWORD dwWriteSize = MultiByteToWideChar(CP_UTF8, NULL, lpcInternetChar, dwCharNumberOfByte,
                lpUnicodeBuffer, *lpBufferNumberOfByte);
            bResult = (dwWriteSize > 0);
            if (bResult) *lpBufferNumberOfByte = dwWriteSize;
        }
        else *lpBufferNumberOfByte = dwNeedSize;
    }
    return bResult;
}

/* Get current UTC UNIX time truncation through SMALLSO Time Server */
time_t GetInternetUtcTimecut(VOID)
{
    time_t tResult = INVALID_TIMECUT;
    HINTERNET hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL);
    if (hInternet)
    {
        HINTERNET hUrl = InternetOpenUrl(hInternet, INTERNET_API_URL, NULL, NULL, INTERNET_FLAG_IGNORE_CERT_CN_INVALID, NULL);
        if (hUrl)
        {
            CHAR szContextBuffer[32] = { NULL };
            DWORD dwReadSize = NULL;
            if (InternetReadFile(hUrl, szContextBuffer, sizeof(szContextBuffer), &dwReadSize)
                && dwReadSize > 0)
            {
                WCHAR szInternetTimecut[32] = { NULL };
                DWORD dwTimecutBufferSize = sizeof(szInternetTimecut);
                if (InternetCharToUnicode(szContextBuffer, dwReadSize, szInternetTimecut, &dwTimecutBufferSize))
                    tResult = (time_t)_wtoi64(szInternetTimecut);
            }
            InternetCloseHandle(hUrl);
        }
        InternetCloseHandle(hInternet);
    }
    return tResult;
}

Demo(main.cpp)

在这段 demo 代码中实现了通过调用 tInternetUtcTimecut 函数请求 SMALLSO Public API 获取 UTC 时间戳;之后调用 TimecutToSystemTime 将 UTC 时间戳转换为 Windows 时间结构 SYSTEMTIME 并由 obSystemTime 变量保存;最后调用 SetSystemTime 将 SYSTEMTIME obSystemTime 传入设置系统时间。

#include "stdafx.h"
#include <time.h>
#include "ontime.h"

int main()
{
    time_t tInternetUtcTimecut = GetInternetUtcTimecut();
    if (tInternetUtcTimecut != INVALID_TIMECUT)
    {
        SYSTEMTIME obSystemTime = { NULL };
        if (TimecutToSystemTime(tInternetUtcTimecut, &obSystemTime, FALSE))
        {
            if (SetSystemTime(&obSystemTime))
                printf("The system time was successfully synchronized with the SMALLSO Time Server.\n");
            else
                printf("Error: Setting system time failed, error code: %d\n", GetLastError());
        }
        else printf("Error: UTC time intercept returned by SMALLSO Time Server is invalid\n");
    }
    else printf("Error: Unable to connect to SMALLSO Time Server, please try again later.\n");
    system("pause");
    return 0;
}

函数原型

time_t 
GetInternetUtcTimecut(
    VOID
);

函数返回值

GetInternetUtcTimecut 返回 time_t 类型(该类型在 time.h 中被定义)

#ifndef _CRT_NO_TIME_T
    #ifdef _USE_32BIT_TIME_T
        typedef __time32_t time_t;
    #else
        typedef __time64_t time_t;
    #endif
#endif
typedef __int64  __time64_t;
typedef long     __time32_t;

通过上述在 time.h(corecrt.h) 中对 time_t 的定义可以看出,当您的应用程序为 64 bit 时,time_t__time64_t,而 32 bit 则为 __time32_t

Demo 下载

VC++:
将 ontime.h 和 ontime.cpp 加入项目并参与编译后包含 ontime.h 即可。

#include "ontime.h"

SDK 下载:ontime-18723.1-release

VC#:
将 nettime.cs 源文件包含至项目后引用 System 命名空间中的 NetTime 类即可。

// 将 nettime.cs 文件包含至当前项目
using System;

SDK 下载:nettime-18726.1-release

Github:SMALLSO/Ontime

0x05 适用环境

0x06 最后

若您发现上述内容中存在错误或不恰当,欢迎通过 Blog 关于页面联系我反馈。

分享您的想法 (2018/3/7 之前的评论与回复将不再显示)
  1. bobo

    关于此API的一个demo,欢迎前来体验访问:https://www.xiaoyy.org/time/

    回复
  2. bobo

    nice

    回复