类库: vc下如何按照当前系统的日期、时间格式显示时间

因为公司要统一所有产品的日期、时间显示格式,要求所有程序在显示日期时间的时候,都默认使用操作系统的时间格式。所以想着封装一个基础类供大家共用。

一开始打算使用EnumDateFormatsExEx和EnumTimeFormatsEx,在win7下开发的,结果同事拿到xp下之后发现直接异常了,然后一看msdn才发现这两个api只有vista之后的操作系统才支持。

所以要改用EnumDateFormatsEx和EnumTimeFormats,但是这两个api没有最后一个PARAM,在封装的时候无法把this传递进去,那么回调就只能把返回的数据存储在全局变量中,但是全局变量的话就无法实现线程安全,怎么办呢?

于是想到了之前看到的TLS,定义如下三个变量。

__declspec(thread)	CString* _dateStr = NULL;
__declspec(thread)	CALID* _calendarID = NULL;
__declspec(thread)	CString* _timeStr = NULL;

回调直接把api返回的值存储到这三个TLS中,然后在类CDateFormatReader的构造函数中再去把他取出来,就ok了。

这样即时多个线程同时使用这个辅助类也没关系。


下面是示例代码:

示例代码如下:

voidCTestGetSystemDateTimeFormatDlg::OnBnClickedBtnGetLongdateformat()
{  
    COleDateTimecurrentTime =COleDateTime::GetCurrentTime();
    CStringstrDate, msg;
    strDate =currentTime.Format(CDateTimeFormatStringReader::GetLongDateFormat());
    msg.Format(_T("format:%s, \nvalue: %s"),CDateTimeFormatStringReader::GetLongDateFormat(), strDate);
    AfxMessageBox(msg);
}
 
 
voidCTestGetSystemDateTimeFormatDlg::OnBnClickedBtnGetLongtimeformat()
{
    COleDateTimecurrentTime =COleDateTime::GetCurrentTime();
    CStringstrDate, msg;   
    strDate =currentTime.Format(CDateTimeFormatStringReader::GetLongTimeFormat());
    msg.Format(_T("format:%s, \nvalue: %s"),CDateTimeFormatStringReader::GetLongTimeFormat(), strDate);
    AfxMessageBox(msg);
}
 
 
voidCTestGetSystemDateTimeFormatDlg::OnBnClickedBtnGetLongdatetimeformat3()
{
    COleDateTimecurrentTime =COleDateTime::GetCurrentTime();
    CStringstrDate, msg;
    strDate =currentTime.Format(CDateTimeFormatStringReader::GetLongDateTimeFormat());
    msg.Format(_T("format:%s, \nvalue: %s"),CDateTimeFormatStringReader::GetLongDateTimeFormat(), strDate);
    AfxMessageBox(msg);
}
 
 
voidCTestGetSystemDateTimeFormatDlg::OnBnClickedBtnGetShortdateformat2()
{
    COleDateTimecurrentTime =COleDateTime::GetCurrentTime();
    CStringstrDate, msg;
    strDate =currentTime.Format(CDateTimeFormatStringReader::GetShortDateFormat());
    msg.Format(_T("format:%s, \nvalue: %s"),CDateTimeFormatStringReader::GetShortDateFormat(), strDate);
    AfxMessageBox(msg);
}
 
 
voidCTestGetSystemDateTimeFormatDlg::OnBnClickedBtnGetShorttimeformat2()
{
    COleDateTimecurrentTime =COleDateTime::GetCurrentTime();
    CStringstrDate, msg;
    strDate =currentTime.Format(CDateTimeFormatStringReader::GetShortTimeFormat());
    msg.Format(_T("format:%s, \nvalue: %s"),CDateTimeFormatStringReader::GetShortTimeFormat(), strDate);
    AfxMessageBox(msg);
}
 
 
voidCTestGetSystemDateTimeFormatDlg::OnBnClickedBtnGetShortdatetimeformat4()
{
    COleDateTimecurrentTime =COleDateTime::GetCurrentTime();
    CStringstrDate, msg;
    strDate =currentTime.Format(CDateTimeFormatStringReader::GetShortDateTimeFormat());
    msg.Format(_T("format:%s, \nvalue: %s"), CDateTimeFormatStringReader::GetShortDateTimeFormat(),strDate);
    AfxMessageBox(msg);
}


完整的封装类的代码如下:

DateTimeFormatStringReader.h

#pragma once

/**
* @class CLongDateTimeFormatStringReader
* @brief 获取当前操作系统的日期、时间格式
*/
class CDateTimeFormatStringReader
{
private:
	/**
	* @class CDateFormatReader
	* @brief 日期格式读取器
	*/
	class CDateFormatReader
	{
	private:
		/** 获取到的时间格式 */
		CString m_dateFormat;

		/**  CalendarID*/
		CALID m_calendarID;

		/** 是否是短日期格式 */
		bool m_isShort;

	private:
		/** 用于配合api的回调 */
		static BOOL CALLBACK EnumDateFormatsProcEx(
			__in  LPTSTR lpDateFormatString,
			__in  CALID CalendarID);
	public:
		CDateFormatReader(bool isShort = false);
	public:
		CString GetOSDateFormat(){ return m_dateFormat;};		
		CString GetDateFormat();
		CALID GetCalendarID(){ return m_calendarID;};
	};	

	/**
	* @class CTimeFormatReader
	* @brief 获取系统时间格式
	*/
	class CTimeFormatReader
	{
	private:
		/** 获取到的时间字符串 */
		CString m_timeFormat;
		/** 是否为短时间格式 */
		bool m_isShort;
	private:
		static BOOL CALLBACK EnumTimeFormatsProc(
			__in  LPTSTR lpTimeFormatString);

	public:
		CTimeFormatReader(bool isShort = false);
		CString GetOSTimeFormat(){ return m_timeFormat;};
		CString GetTimeFormat();
	};

public:
	static CString GetLongDateFormat();	
	static CString GetLongTimeFormat();
	static CString GetLongDateTimeFormat();

	static CString GetShortDateFormat();
	static CString GetShortTimeFormat();
	static CString GetShortDateTimeFormat();

	/** 短期日、长时间格式,这是推荐的格式 */
	static CString GetShortDateLongTimeFormat();
	static CString GetShortDateLongTimeFormatWithMilliSecond();

	static CALID GetCalendarId();
};


DateTimeFormatStringReader.cpp

#include "StdAfx.h"
#include "DateTimeFormatStringReader.h"


/**
* 本来打算就使用几个文件内的局部变量来存放回调函数返回的只,
* 但是这样的话就不是线程安全的了,所以改用线程局部变量来存储回调函数返回的值,这样就可以实现线程安全
*/
__declspec(thread)	CString* _dateStr = NULL;
__declspec(thread)	CALID* _calendarID = NULL;
__declspec(thread)	CString* _timeStr = NULL;

bool IsWindows7Later()
{
	OSVERSIONINFO osvi;
	ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&osvi);
	TCHAR szVersion[10] = {0};
	CString strVersion;
	strVersion.Format(_T("%d.%d"), osvi.dwMajorVersion, osvi.dwMinorVersion);
	return strVersion.Compare(_T("6.1")) >= 0;
}


CDateTimeFormatStringReader::CDateFormatReader::CDateFormatReader( bool isShort ):m_isShort(isShort)
{
	m_dateFormat = "";
	m_calendarID = 0;

	DWORD dwFlags = DATE_LONGDATE;
	if(m_isShort)
		dwFlags = DATE_SHORTDATE;	

	BOOL dwReturn = EnumDateFormatsEx(EnumDateFormatsProcEx, LOCALE_USER_DEFAULT, dwFlags);
	ASSERT(dwReturn);
	if(_dateStr != NULL)
	{
		this->m_dateFormat = *_dateStr;
		delete _dateStr;
		_dateStr = NULL;
	}
	if(_calendarID != NULL)
	{
		this->m_calendarID = *_calendarID;
		delete _calendarID;
		_calendarID = NULL;
	}		
}

BOOL CALLBACK CDateTimeFormatStringReader::CDateFormatReader::EnumDateFormatsProcEx( __in LPTSTR lpDateFormatString, __in CALID calendarID)
{	
	//把取过来的只存放在tls中,然后在后续的函数方法中去使用和释放
	//以便实现线程安全
	_dateStr = new CString(lpDateFormatString);	
	_calendarID = new CALID(calendarID);	
	return FALSE;
}

CString CDateTimeFormatStringReader::CDateFormatReader::GetDateFormat()
{
	CString formatStr = GetOSDateFormat();
	formatStr.Replace(_T("'"), _T(""));
	if(formatStr.Find(_T("yyyy"))>=0)
		formatStr.Replace(_T("yyyy"), _T("%Y"));
	if(formatStr.Find(_T("yy"))>=0)
		formatStr.Replace(_T("yy"), _T("%y"));

	if(formatStr.Find(_T("MMMM"))>=0)
		formatStr.Replace(_T("MMMM"), _T("%B"));
	else if(formatStr.Find(_T("MMM"))>=0)
		formatStr.Replace(_T("MMM"), _T("%b"));
	else if(formatStr.Find(_T("MM"))>=0)
		formatStr.Replace(_T("MM"), _T("%m"));
	else if(formatStr.Find(_T("M"))>=0)
		formatStr.Replace(_T("M"), _T("%m"));

	if(formatStr.Find(_T("dddd"))>=0)
		formatStr.Replace(_T("dddd"), _T("%A"));
	if(formatStr.Find(_T("ddd"))>=0)
		formatStr.Replace(_T("ddd"), _T("%a"));

	if(formatStr.Find(_T("dd"))>=0)
		formatStr.Replace(_T("dd"), _T("%d"));
	else if(formatStr.Find(_T("d"))>=0)
		formatStr.Replace(_T("d"), _T("%d"));

	return formatStr;
}


//
CDateTimeFormatStringReader::CTimeFormatReader::CTimeFormatReader(bool isShort):m_isShort(isShort)
{
	DWORD dwFlag = 0;
	bool isWin7OrLater = IsWindows7Later();
	if(isShort && isWin7OrLater)
		dwFlag |= TIME_NOSECONDS;
	BOOL dwReturn = EnumTimeFormats(EnumTimeFormatsProc, LOCALE_USER_DEFAULT, dwFlag);
	ASSERT(dwReturn);
	if(_timeStr != NULL)
	{
		this->m_timeFormat = *_timeStr;
		if(isShort && !isWin7OrLater)
			m_timeFormat.Replace(_T(":ss"), _T(""));
		delete _timeStr;
		_timeStr = NULL;
	}
}

BOOL CALLBACK CDateTimeFormatStringReader::CTimeFormatReader::EnumTimeFormatsProc( __in LPTSTR lpTimeFormatString)
{
	//把取过来的只存放在tls中,然后在后续的函数方法中去使用和释放
	//以便实现线程安全
	_timeStr = new CString(lpTimeFormatString);	
	return FALSE;
}

CString CDateTimeFormatStringReader::CTimeFormatReader::GetTimeFormat()
{
	CString formatStr = GetOSTimeFormat();
	if(formatStr.Find(_T("HH"))>=0)
		formatStr.Replace(_T("HH"), _T("%H"));
	else if(formatStr.Find(_T("H"))>=0)
		formatStr.Replace(_T("H"), _T("%H"));

	if(formatStr.Find(_T("hh"))>=0)
		formatStr.Replace(_T("hh"), _T("%I"));
	else if(formatStr.Find(_T("h"))>=0)
		formatStr.Replace(_T("h"), _T("%I"));

	if(formatStr.Find(_T("mm"))>=0)
		formatStr.Replace(_T("mm"), _T("%M"));
	else if(formatStr.Find(_T("m"))>=0)
		formatStr.Replace(_T("m"), _T("%M"));

	if(formatStr.Find(_T("ss"))>=0)
		formatStr.Replace(_T("ss"), _T("%S"));
	else if(formatStr.Find(_T("s"))>=0)
		formatStr.Replace(_T("s"), _T("%S"));

	if(formatStr.Find(_T("tt"))>=0)
		formatStr.Replace(_T("tt"), _T("%p"));
	return formatStr;
}

//
CString CDateTimeFormatStringReader::GetLongDateFormat()
{
	CDateFormatReader dateFormatReader;
	return dateFormatReader.GetDateFormat();
}

CString CDateTimeFormatStringReader::GetLongTimeFormat()
{
	CTimeFormatReader timeFormatReader;
	return timeFormatReader.GetTimeFormat();
}

CString CDateTimeFormatStringReader::GetLongDateTimeFormat()
{
	CString result;
	result.Format(_T("%s %s"), GetLongDateFormat(), GetLongTimeFormat());
	return result;
}

CString CDateTimeFormatStringReader::GetShortDateFormat()
{
	CDateFormatReader dateFormatReader(true);
	return dateFormatReader.GetDateFormat();
}

CString CDateTimeFormatStringReader::GetShortTimeFormat()
{
	CTimeFormatReader timeFormatReader(true);
	return timeFormatReader.GetTimeFormat();

}

CString CDateTimeFormatStringReader::GetShortDateTimeFormat()
{
	CString result;
	result.Format(_T("%s %s"), GetShortDateFormat(), GetShortTimeFormat());
	return result;
}

CALID CDateTimeFormatStringReader::GetCalendarId()
{
	CDateFormatReader dateFormatReader(true);
	return dateFormatReader.GetCalendarID();
}

CString CDateTimeFormatStringReader::GetShortDateLongTimeFormat()
{
	CString result;
	result.Format(_T("%s %s"), GetShortDateFormat(), GetLongTimeFormat());
	return result;
}

CString CDateTimeFormatStringReader::GetShortDateLongTimeFormatWithMilliSecond()
{
	CString result;
	result.Format(_T("%s %s"), GetShortDateFormat(), GetLongTimeFormat());
	if(result.Find(_T("%S")) >= 0)
		result.Replace(_T("%S"), _T("%S.milliSecond"));
	return result;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值