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

in 开源 with 2 comments

这是一个历史遗留的 Web API,现已下线。

0x01 前言

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

0x02 描述

接口描述

输入参数

参数名称必选类型描述
typeString获取的时间类型(cut,time)
formatString输出的时间格式(例如:yyyy/MM/dd)
utcBoolean是否输出 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 关于页面联系我反馈。

分享您的观点
  1. bobo

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

    回复
  2. bobo

    nice

    回复