64位时间戳实现

实现了64位时间戳,可以表示公元1年1月1日零时至9999年12月31日末时之间的时刻,精确到毫秒。

 

/*-----------------------------------------------------
	Author: http://blog.csdn.net/xinghongduo
	E-Mail: 317358117@qq.com
	Description: 64位时间戳,可以表示的时间范围是
	(0001-01-01 00:00:00:000 ~ 9999-12-31 23:59:59:999)
	精确到毫秒
------------------------------------------------------*/

#ifndef MY_TIME_H_
#define MY_TIME_H_

#include <windows.h>

typedef  __int64 time64;
#define MilSecondPerDay 86400000

class MyTimestamp
{

private:

	void parseDateString(char* ,time64**);
	time64 transformToTimestamp(time64 ,time64 ,time64 ,time64 ,time64 ,time64 ,time64);
	void transformToDate(time64 ,time64**);
	time64 getDateTimestamp(int ,int ,int);

public:

	time64 getCurrentTimestamp();
	time64 transformToTimestamp(char*);
	void transformToDateString(time64 ,char*);

	long time64ToUnixTime(time64);
	time64 unixTimeToTime64(long);

	int dateFunction(char* ,char*);
	int dateFunction(char* ,time64);

	time64 dateAdd(char* ,char* ,int ,char*);

	MyTimestamp(){};
	~MyTimestamp(){};
};


/*
获得当前时间的时间戳
*/
time64 MyTimestamp::getCurrentTimestamp()
{
	SYSTEMTIME t;
    time64 year ,month ,day ,hour ,min ,sec ,mil;

    GetLocalTime(&t);
    year = t.wYear;
    month = t.wMonth;
    day = t.wDay;
    hour = t.wHour;
    min = t.wMinute;
    sec = t.wSecond;
    mil = t.wMilliseconds;

	return transformToTimestamp(year ,
        month ,day ,
        hour ,min ,
        sec ,mil );
}


/*
将时间格式字符串转化为时间戳
*/
time64 MyTimestamp::transformToTimestamp(char *dateString)
{
	time64 year ,month ,day ,hour ,minute ,second ,milliSecond;
    time64 *intp[] = {&year ,&month ,&day ,&hour ,
        &minute ,&second ,&milliSecond };

	parseDateString(dateString ,intp );

	return transformToTimestamp(year ,
        month ,day ,
        hour ,minute ,
        second ,milliSecond );
}


/*
转化为时间戳(内部调用)
*/
time64 MyTimestamp::transformToTimestamp(time64 year ,
                                    time64 month ,time64 day ,
                                    time64 hour ,time64 min ,
                                    time64 sec ,time64 mil )
{
    time64 ret;

    static time64 daySum[] = {0 ,31 ,59 ,90 ,120 ,151 ,181 ,212 ,243 ,273 ,304 ,334 };

    ret = ((year-1)*365  + (year-1)/4 - (year-1)/100 + (year-1)/400) * 24 * 3600;

    ret += daySum[month-1] * 24 * 3600;

    if(month > 2 && (( (year&3)==0 && year%100!=0) || year%400==0))
        ret += 24 * 3600;

    ret += ((day-1) * 24 + hour) * 3600 + min * 60 + sec;

    return ret * 1000 + mil;
}


/*
将64位时间戳转化为时间字符串
*/
void MyTimestamp::transformToDateString(time64 timeStamp ,char *dateString)
{
	time64 year ,month ,day ,hour ,minute ,second ,milliSecond;
    time64 *intp[] = {&year ,&month ,&day ,&hour ,
        &minute ,&second ,&milliSecond };

	transformToDate(timeStamp ,intp);

    sprintf(dateString ,"%.4I64d-%.2I64d-%.2I64d %.2I64d:%.2I64d:%.2I64d:%.3I64d" ,
        year ,month ,day+1 ,hour ,minute ,second ,milliSecond );
}


/*
将64位时间戳转化为时间数组
*/
void MyTimestamp::transformToDate(time64 timeStamp ,time64 **dateArry)
{
    time64 low ,high ,mid ,t;
    time64 year ,month ,day ,hour ,minute ,second ,milliSecond;
    time64 daySum[] = {0 ,31 ,59 ,90 ,120 ,151 ,181 ,212 ,243 ,273 ,304 ,334 ,365};
    time64 milOfDay = 24 * 3600 * 1000;
    time64 milOfHour = 3600 * 1000;

    /*防止超过9999-12-31 23:59:59:999*/
	if(timeStamp > 315537897599999) {
		timeStamp = 315537897599999;
	}

    low = 1;
    high = 9999;

    while(low <= high)
    {
        mid = (low+high)>>1;
        t = ((mid-1) * 365 + (mid-1)/4 - (mid-1)/100 + (mid-1)/400) * milOfDay;

        if(t == timeStamp)
        {
            low = mid + 1;
            break;
        }
        else if(t < timeStamp)
            low = mid + 1;
        else
            high = mid - 1;
    }
    year = low-1;
    timeStamp -= ((year-1) * 365 + (year-1)/4 - (year-1)/100 + (year-1)/400) * milOfDay;

	bool isLeapYear = ((year&3) == 0 && year%100!=0) || year%400 == 0;

	for(month = 1 ;(daySum[month] + ((isLeapYear && month > 1) ? 1 : 0)) * milOfDay <= timeStamp && month < 13 ;month ++) {
		if(isLeapYear && month > 1)
			++daySum[month];
	}
    timeStamp -= daySum[month-1] * milOfDay;

    day = timeStamp / milOfDay;
    timeStamp -= day * milOfDay;

    hour = timeStamp / milOfHour;
    timeStamp -= hour * milOfHour;

    minute = timeStamp / 60000;
    timeStamp -= minute * 60000;

    second = timeStamp / 1000;
    milliSecond = timeStamp % 1000;

	*dateArry[0] = year;
	*dateArry[1] = month;
	*dateArry[2] = day;
	*dateArry[3] = hour;
	*dateArry[4] = minute;
	*dateArry[5] = second;
	*dateArry[6] = milliSecond;
}


/*
解析形如2013-7-1 10:20:30:550的时间字符串
*/
void MyTimestamp::parseDateString(char *dateString ,time64 **arry)
{
	int i;
	time64 t;
	const char *p = dateString;

    for(i = 0 ; i < 7 ;i ++)
		*arry[i] = i<3 ? 1 : 0;

    for(i = 0 ; i < 7 ;i ++)
    {
        for(t = 0 ; *p >= '0' && *p <= '9' && *p != '\0' ;++p)
            t = t * 10 + *p - 48;
    
        *arry[i] = t;
        while( (*p < '0' || *p > '9') && *p != '\0')
            ++p;

        if('\0' == *p)
            break;
    }
}


/*
将64位时间戳转化为UNIX时间戳
*/
long MyTimestamp::time64ToUnixTime(time64 timeStamp)
{
	time64 unixStart = 62135596800000;
	if(timeStamp < unixStart) {
		timeStamp = unixStart;
	}
	return (long)((timeStamp-unixStart)/1000);
}


/*
将UNIX时间戳转化为64位时间戳
*/
time64 MyTimestamp::unixTimeToTime64(long unix)
{
	time64 unixStart = 62135596800000 ,t = unix;
	unixStart += t * 1000;
	return unixStart;
}


/*
功能类似SQL Server中的datename函数
type取值范围:
"weekDay" 返回是周几
"weekYear" 返回该年有多少周
*/
int MyTimestamp::dateFunction(char *type ,char *dateString)
{
	int cmp_res;
	time64 timeStamp = transformToTimestamp(dateString);
	return dateFunction(type ,timeStamp);
}


/*
获得year年month月day日0:0:0:0的时间戳
*/
time64 MyTimestamp::getDateTimestamp(int year ,int month ,int day)
{
	char dateString[30];

	sprintf_s(dateString ,30 ,"%d-%d-%d" ,year ,month ,day);

	return transformToTimestamp(dateString);
}


int MyTimestamp::dateFunction(char *type ,time64 timeStamp)
{
	int cmp_res;
	time64 year ,month ,day ,hour ,minute ,second ,milliSecond;
    time64 *intp[] = {&year ,&month ,&day ,&hour ,
        &minute ,&second ,&milliSecond };

	transformToDate(timeStamp ,intp);

	cmp_res = stricmp(type ,"weekday");
	if(0 == cmp_res) {

		return (timeStamp/MilSecondPerDay)%7+1;

	} else {

		time64 yStart ,yEnd;
		int days ,sWeekday ,eWeekday;

		yStart = getDateTimestamp(year ,1 ,1);
		yEnd = getDateTimestamp(year ,12 ,31 );
		sWeekday = dateFunction("weekday" ,yStart);
		eWeekday = dateFunction("weekday" ,yEnd);
		days = (yEnd-yStart)/MilSecondPerDay+1;
		days -= 8-sWeekday;
		return days/7+1;

	}
}


/*
时间计算,dateString时间加上add后的日期
type值
DAY
HOUR
MICROSECOND
MINUTE
SECOND
WEEK
*/
time64 MyTimestamp::dateAdd(char *dateString ,char* newDateString ,int add ,char* type)
{
	int i;
	const char *allType[] = {"day" ,"hour" ,"microsecond" ,"minute" ,"second" ,"week"};
	static const time64 addOfType[] = {MilSecondPerDay ,3600000 ,add ,60000 ,1000 ,7*MilSecondPerDay};
	time64 timeStamp = 0;

	for(i = 0 ;stricmp(allType[i] ,type) && i < 6 ;i ++);

	if(i == 6) {
		strcpy_s(newDateString ,sizeof("type类型错误!") ,"type类型错误!");
	} else {

		timeStamp = transformToTimestamp(dateString);
		timeStamp += add * addOfType[i];

		transformToDateString(timeStamp ,newDateString);
	}
	return timeStamp;
}


#endif

 

#include <iostream>
#include "MyTimestamp.h"
using namespace std;

int main(int argc ,char **argv)
{
	char dateString[30];
    MyTimestamp s;
    time64 currentTime ,t2038;

    currentTime = s.getCurrentTimestamp();
    s.transformToDateString(currentTime ,dateString);
    
    cout<<"当前时间 "<<dateString<<endl;
    cout<<"当前时间戳"<<currentTime<<endl;
    cout<<"当前时间的UNIX时间戳 "<<s.time64ToUnixTime(currentTime)<<endl;

    s.dateAdd(dateString ,dateString ,30 ,"day");
    cout<<"当前时间后30天的时间为"<<dateString<<endl;

    //2038年问题
    t2038 = s.unixTimeToTime64(0x7FFFFFFF);
    s.transformToDateString(t2038 ,dateString);
    cout<<"UNIX时间戳表示的最大时间 "<<dateString<<endl;

	return 0;
}


 

可信时间戳是指一种数字签名技术,可以证明某个数字签名是在特定的时间之前完成的。Java中可以使用Bouncy Castle库来实现可信时间戳功能。 以下是一个简单的Java代码示例,用于生成和验证可信时间戳: ```java import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Hashtable; import java.util.Vector; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cms.AttributeTable; import org.bouncycastle.asn1.cms.ContentInfo; import org.bouncycastle.asn1.cms.SignedData; import org.bouncycastle.asn1.cms.TimeStampToken; import org.bouncycastle.asn1.tsp.MessageImprint; import org.bouncycastle.asn1.tsp.TSTInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.cms.CMSException; import org.bouncycastle.cms.CMSSignedData; import org.bouncycastle.cms.CMSSignedDataGenerator; import org.bouncycastle.cms.CMSTypedData; import org.bouncycastle.cms.SignerInfoGenerator; import org.bouncycastle.cms.SignerInformation; import org.bouncycastle.cms.SignerInformationGenerator; import org.bouncycastle.cms.SignerInformationStore; import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; import org.bouncycastle.operator.DigestAlgorithmIdentifierFinder; import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder; import org.bouncycastle.tsp.TSPException; import org.bouncycastle.tsp.TimeStampRequest; import org.bouncycastle.tsp.TimeStampRequestGenerator; import org.bouncycastle.tsp.TimeStampResponse; import org.bouncycastle.tsp.TimeStampTokenGenerator; public class TrustedTimestamp { public static void main(String[] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); // 输入要签名的数据 byte[] data = "Hello World".getBytes(); // 创建时间戳请求 TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator(); reqGen.setCertReq(true); byte[] digest = getMessageDigest(data); TimeStampRequest req = reqGen.generate( new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"), digest); // 发送时间戳请求并接收响应 byte[] tsTokenBytes = getTimestampToken(req.getEncoded()); // 解析时间戳响应并验证签名 TimeStampToken tsToken = new TimeStampToken(new ContentInfo( SignedData.getInstance(tsTokenBytes))); if (tsToken.isSignatureValid(new SignerInformationStore( tsToken.getSignedContent() .getContentInfo() .getContentType(), tsToken.getSignedContent() .getContentInfo() .getContent()))) { System.out.println("Timestamp signature verified."); } else { System.out.println("Timestamp signature verification failed!"); } // 验证时间戳中的原文摘要值与输入数据的摘要值是否一致 TSTInfo tstInfo = tsToken.getTimeStampInfo().toTSTInfo(); if (MessageDigest.isEqual(digest, tstInfo.getMessageImprint() .getHashedMessage())) { System.out.println("Message digest verified."); } else { System.out.println("Message digest verification failed!"); } } private static byte[] getMessageDigest(byte[] data) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("SHA-256"); return md.digest(data); } private static byte[] getTimestampToken(byte[] request) throws IOException, OperatorCreationException, CertificateEncodingException, TSPException { // 时间戳服务URL String url = "http://timestamp.comodoca.com/authenticode"; // 时间戳服务用户名 String username = "username"; // 时间戳服务密码 String password = "password"; // 创建时间戳请求对象 Hashtable<String, String> headers = new Hashtable<>(); headers.put("Content-Type", "application/timestamp-query"); headers.put("Authorization", "Basic " + Base64.getEncoder().encodeToString((username + ":" + password).getBytes())); HttpTimestamper timestamper = new HttpTimestamper(url, headers); // 获取时间戳响应数据 TimeStampResponse response = timestamper.generateTimeStampResponse(request); // 提取时间戳令牌 TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator( new JcaSignerInfoGeneratorBuilder( new BcDigestCalculatorProvider()) .build(new BcRSAContentSignerBuilder( response.getTimeStampToken().getSignedData() .getDigestAlgorithm(), response.getTimeStampToken().getSignedData() .getEncapContentInfo() .getContentEncryptionAlgorithm()) .build(response.getTimeStampToken() .getSignerInfos() .getSigners() .iterator() .next() .getPrivateKey()))); tsTokenGen.setAccuracySeconds(1); tsTokenGen.setAccuracyMillis(0); tsTokenGen.setAccuracyMicros(0); tsTokenGen.setTSA(new X509Certificate[]{response.getTimeStampToken() .getCertificates()[0]}); return tsTokenGen.generate(new CMSProcessableByteArray(request), false).getEncoded(); } private static class HttpTimestamper { private final String url; private final Hashtable<String, String> headers; HttpTimestamper(String url, Hashtable<String, String> headers) { this.url = url; this.headers = headers; } TimeStampResponse generateTimeStampResponse(byte[] request) throws IOException, TSPException { byte[] response = post(url, request, headers); return new TimeStampResponse(response); } private static byte[] post(String url, byte[] data, Hashtable<String, String> headers) throws IOException { HttpURLConnection conn = (HttpURLConnection) new URL(url) .openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestProperty("Content-Type", headers.get("Content-Type")); for (String key : headers.keySet()) { if (!key.equalsIgnoreCase("Content-Type")) { conn.setRequestProperty(key, headers.get(key)); } } OutputStream out = conn.getOutputStream(); out.write(data); out.close(); InputStream in = conn.getInputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[8192]; int count; while ((count = in.read(buffer)) != -1) { baos.write(buffer, 0, count); } in.close(); return baos.toByteArray(); } } } ``` 代码中通过Bouncy Castle库实现时间戳的生成和验证。在生成时间戳的过程中,需要调用时间戳服务的API来获取时间戳响应数据,并将响应数据转换为时间戳令牌;在验证时间戳的过程中,需要校验时间戳令牌的签名和原文摘要值。 注意,为了使用Bouncy Castle库,需要在代码中添加以下语句: ```java import org.bouncycastle.jce.provider.BouncyCastleProvider; Security.addProvider(new BouncyCastleProvider()); ``` 同时,为了使用时间戳服务,需要替换代码中的时间戳服务URL、用户名和密码。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值