Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

strftime Substitution Token Viewer

0.00/5 (No votes)
20 Jun 2018 1  
This article demonstrates every documented strftime substitution token, and provides a tool to generate your own list for your platform.

Introduction

Since I plan to retire the 32-bit C library that I created years ago to support the system utilities that I was creating, mostly in C, with a sprinkling of standard C++ in favor of a new oune built around the strftime function that is part of the standard C runtime library, I wanted a ready reference that showed unequivocally what each token does. I harvested my list of substitution tokens from https://msdn.microsoft.com/en-us/library/fe06s4ak.aspx.

Background

Unless you use a string formatting routine pretty regularly, it's hard to remember what each of the various substitution tokens for such library routines as strftime and printf do. Compounding the matter is that some of the descriptions are a tad confusing. My solution is a tool that uses each token, in turn, in a call to strftime. As a bonus, the report starts with a display of the current machine time that uses the most common tokens. Since I needed to get the data into Excel, so that I could add it to my workbook of quick references, the tool creates a tab delimited report as a by-product.

Following is the output written to the console by the version of the tool that is included in the code sample.

Microsoft Windows [Version 10.0.17134.112]
(c) 2018 Microsoft Corporation. All rights reserved.


C:\Users\DAG\Documents\Articles_2018\NTFS_File_Times_in_CMD\SpiderOak_Directory_Watcher_etc\spideroak_windows_dir_watcher\NOTES 2018/06/20 14:09:25.68>F:\Source_Code\Visual_Studio\Projects\_Laboratory\StrfTime_Token_Demo\Release\StrfTime_Token_Demo.exe
Showing all 23 individual strftime substitution tokens, raw and modifed:

Time used for all tests = 2018/06/20 14:09:33 Central Daylight Time

Case  1: Abbreviated weekday name:

         Raw Token:      %a  = Wed
         Modified Token: %#a = Wed

Case  2: Full weekday name:

         Raw Token:      %A  = Wednesday
         Modified Token: %#A = Wednesday

Case  3: Abbreviated month name:

         Raw Token:      %b  = Jun
         Modified Token: %#b = Jun

Case  4: Full month nam:

         Raw Token:      %B  = June
         Modified Token: %#B = June

Case  5: Date and time representation appropriate for locale:

         Raw Token:      %c  = Wed Jun 20 14:09:33 2018
         Modified Token: %#c = Wednesday, June 20, 2018 14:09:33

Case  6: Day of month as decimal number (01 ? 31):

         Raw Token:      %d  = 20
         Modified Token: %#d = 20

Case  7: Hour in 24-hour format (00 ? 23):

         Raw Token:      %H  = 14
         Modified Token: %#H = 14

Case  8: Hour in 12-hour format (01 ? 12):

         Raw Token:      %I  = 02
         Modified Token: %#I = 2

Case  9: Day of year as decimal number (001 ? 366):

         Raw Token:      %j  = 171
         Modified Token: %#j = 171

Case 10: Month as decimal number (01 ? 12):

         Raw Token:      %m  = 06
         Modified Token: %#m = 6

Case 11: Minute as decimal number (00 ? 59):

         Raw Token:      %M  = 09
         Modified Token: %#M = 9

Case 12: Current locale's A.M./P.M. indicator for 12-hour clock:

         Raw Token:      %p  = PM
         Modified Token: %#p = PM

Case 13: Second as decimal number (00 ? 59):

         Raw Token:      %S  = 33
         Modified Token: %#S = 33

Case 14: Week of year as decimal number, with Sunday as first day of week (00 ? 53):

         Raw Token:      %U  = 24
         Modified Token: %#U = 24

Case 15: Week of year as decimal number, with Monday as first day of week (00 ? 53):

         Raw Token:      %W  = 25
         Modified Token: %#W = 25

Case 16: Weekday as decimal number (0 ? 6; Sunday is 0):

         Raw Token:      %w  = 3
         Modified Token: %#w = 3

Case 17: Date representation for current locale:

         Raw Token:      %x  = 06/20/18
         Modified Token: %#x = Wednesday, June 20, 2018

Case 18: Time representation for current locale:

         Raw Token:      %X  = 14:09:33
         Modified Token: %#X = 14:09:33

Case 19: Year without century, as decimal number (00 ? 99):

         Raw Token:      %y  = 18
         Modified Token: %#y = 18

Case 20: Year with century, as decimal number:

         Raw Token:      %Y  = 2018
         Modified Token: %#Y = 2018

Case 21: Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown:

         Raw Token:      %z  = -0500
         Modified Token: %#z = -0500

Case 22: Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown:

         Raw Token:      %Z  = Central Daylight Time
         Modified Token: %#Z = Central Daylight Time

Case 23: Percent sign (The doubled percent sign behaves in the standard way to suppress the default intepretation of the % character.):

         Raw Token:      %%  = %
         Modified Token: %#% = %

A tab-delmited report is in C:\Users\DAG\Documents\Articles_2018\NTFS_File_Times_in_CMD\SpiderOak_Directory_Watcher_etc\spideroak_windows_dir_watcher\NOTES\StrfTime_Token_Demo.TSV.
Done: press Enter to exit program.

C:\Users\DAG\Documents\Articles_2018\NTFS_File_Times_in_CMD\SpiderOak_Directory_Watcher_etc\spideroak_windows_dir_watcher\NOTES 2018/06/20 14:09:57.86>
Sample archive strftime_Samples_20180620_145841.zip contains two files.
  1. StrfTime_Token_Demo_Debug_20180619_223755.TSV is the report generated by a previous run, before I added the name of the output file to the end of the report.
  2. StrfTime_Token_Demo_Debug_20180619_223755.xlsx is the Excel worksheet that I created by importing the tab delimited file listed just above.

Since the files were generated by the last run before I added the file name to the report, the reference time stamp and the 23 output values differ from those shown above.

Using the code

Since such a tool can benefit any programmer who writes in C and C++, I took exceptional pains to confine myself to standard library routines, so that the source should compile on any platform that supports one or more ANSI C compilers.

If your platform is Microsoft Windows and your C compiler is any recent Microsoft Visual C++ edition, the solution should open and build as is. The project includes both debug and release configuration build outputs generated on my machine, which runs Visual Studio 2017 atop Windows 10 Pro x64, version 1803. Although the solution defines both x86 and x64 configurations, I built only the x86 configurations, leaving the x64 build as an exercise.

To build it on another OS or with a different compiler, the only part that you may need to adjust is the first header, targetver.h, which contains yet another include directive.

#pragma once

// Including SDKDDKVer.h defines the highest available Windows platform.

// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.

#include <SDKDDKVer.h>

Unless your build tools include SDKDDKVer.h, you must find a suitable substitute. For your reference, below is a listing of its contents.

/*

Copyright (c) Microsoft Corporation. All rights reserved.

Module Name:

    sdkddkver.h

Abstract:

    Master include file for versioning windows SDK/DDK.

*/

#ifndef _INC_SDKDDKVER
#define _INC_SDKDDKVER

#if (_MSC_VER >= 800)
#if (_MSC_VER >= 1200)
#pragma warning(push)
#pragma warning(disable:4668) /* #if not_defined treated as #if 0 */
#endif
#pragma warning(disable:4001) /* nonstandard extension : single line comment */
#endif

#pragma once

//
// _WIN32_WINNT version constants
//
#define _WIN32_WINNT_NT4                    0x0400
#define _WIN32_WINNT_WIN2K                  0x0500
#define _WIN32_WINNT_WINXP                  0x0501
#define _WIN32_WINNT_WS03                   0x0502
#define _WIN32_WINNT_WIN6                   0x0600
#define _WIN32_WINNT_VISTA                  0x0600
#define _WIN32_WINNT_WS08                   0x0600
#define _WIN32_WINNT_LONGHORN               0x0600
#define _WIN32_WINNT_WIN7                   0x0601
#define _WIN32_WINNT_WIN8                   0x0602
#define _WIN32_WINNT_WINBLUE                0x0603
#define _WIN32_WINNT_WINTHRESHOLD           0x0A00 /* ABRACADABRA_THRESHOLD*/
#define _WIN32_WINNT_WIN10                  0x0A00 /* ABRACADABRA_THRESHOLD*/

//
// _WIN32_IE_ version constants
//
#define _WIN32_IE_IE20                      0x0200
#define _WIN32_IE_IE30                      0x0300
#define _WIN32_IE_IE302                     0x0302
#define _WIN32_IE_IE40                      0x0400
#define _WIN32_IE_IE401                     0x0401
#define _WIN32_IE_IE50                      0x0500
#define _WIN32_IE_IE501                     0x0501
#define _WIN32_IE_IE55                      0x0550
#define _WIN32_IE_IE60                      0x0600
#define _WIN32_IE_IE60SP1                   0x0601
#define _WIN32_IE_IE60SP2                   0x0603
#define _WIN32_IE_IE70                      0x0700
#define _WIN32_IE_IE80                      0x0800
#define _WIN32_IE_IE90                      0x0900
#define _WIN32_IE_IE100                     0x0A00
#define _WIN32_IE_IE110                     0x0A00  /* ABRACADABRA_THRESHOLD */

//
// IE <-> OS version mapping
//
// NT4 supports IE versions 2.0 -> 6.0 SP1
#define _WIN32_IE_NT4                       _WIN32_IE_IE20
#define _WIN32_IE_NT4SP1                    _WIN32_IE_IE20
#define _WIN32_IE_NT4SP2                    _WIN32_IE_IE20
#define _WIN32_IE_NT4SP3                    _WIN32_IE_IE302
#define _WIN32_IE_NT4SP4                    _WIN32_IE_IE401
#define _WIN32_IE_NT4SP5                    _WIN32_IE_IE401
#define _WIN32_IE_NT4SP6                    _WIN32_IE_IE50
// Win98 supports IE versions 4.01 -> 6.0 SP1
#define _WIN32_IE_WIN98                     _WIN32_IE_IE401
// Win98SE supports IE versions 5.0 -> 6.0 SP1
#define _WIN32_IE_WIN98SE                   _WIN32_IE_IE50
// WinME supports IE versions 5.5 -> 6.0 SP1
#define _WIN32_IE_WINME                     _WIN32_IE_IE55
// Win2k supports IE versions 5.01 -> 6.0 SP1
#define _WIN32_IE_WIN2K                     _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP1                  _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP2                  _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP3                  _WIN32_IE_IE501
#define _WIN32_IE_WIN2KSP4                  _WIN32_IE_IE501
#define _WIN32_IE_XP                        _WIN32_IE_IE60
#define _WIN32_IE_XPSP1                     _WIN32_IE_IE60SP1
#define _WIN32_IE_XPSP2                     _WIN32_IE_IE60SP2
#define _WIN32_IE_WS03                      0x0602
#define _WIN32_IE_WS03SP1                   _WIN32_IE_IE60SP2
#define _WIN32_IE_WIN6                      _WIN32_IE_IE70
#define _WIN32_IE_LONGHORN                  _WIN32_IE_IE70
#define _WIN32_IE_WIN7                      _WIN32_IE_IE80
#define _WIN32_IE_WIN8                      _WIN32_IE_IE100
#define _WIN32_IE_WINBLUE                   _WIN32_IE_IE100
#define _WIN32_IE_WINTHRESHOLD              _WIN32_IE_IE110  /* ABRACADABRA_THRESHOLD */
#define _WIN32_IE_WIN10                     _WIN32_IE_IE110  /* ABRACADABRA_THRESHOLD */


//
// NTDDI version constants
//
#define NTDDI_WIN2K                         0x05000000
#define NTDDI_WIN2KSP1                      0x05000100
#define NTDDI_WIN2KSP2                      0x05000200
#define NTDDI_WIN2KSP3                      0x05000300
#define NTDDI_WIN2KSP4                      0x05000400

#define NTDDI_WINXP                         0x05010000
#define NTDDI_WINXPSP1                      0x05010100
#define NTDDI_WINXPSP2                      0x05010200
#define NTDDI_WINXPSP3                      0x05010300
#define NTDDI_WINXPSP4                      0x05010400

#define NTDDI_WS03                          0x05020000
#define NTDDI_WS03SP1                       0x05020100
#define NTDDI_WS03SP2                       0x05020200
#define NTDDI_WS03SP3                       0x05020300
#define NTDDI_WS03SP4                       0x05020400

#define NTDDI_WIN6                          0x06000000
#define NTDDI_WIN6SP1                       0x06000100
#define NTDDI_WIN6SP2                       0x06000200
#define NTDDI_WIN6SP3                       0x06000300
#define NTDDI_WIN6SP4                       0x06000400

#define NTDDI_VISTA                         NTDDI_WIN6
#define NTDDI_VISTASP1                      NTDDI_WIN6SP1
#define NTDDI_VISTASP2                      NTDDI_WIN6SP2
#define NTDDI_VISTASP3                      NTDDI_WIN6SP3
#define NTDDI_VISTASP4                      NTDDI_WIN6SP4

#define NTDDI_LONGHORN  NTDDI_VISTA

#define NTDDI_WS08                          NTDDI_WIN6SP1
#define NTDDI_WS08SP2                       NTDDI_WIN6SP2
#define NTDDI_WS08SP3                       NTDDI_WIN6SP3
#define NTDDI_WS08SP4                       NTDDI_WIN6SP4

#define NTDDI_WIN7                          0x06010000
#define NTDDI_WIN8                          0x06020000
#define NTDDI_WINBLUE                       0x06030000
#define NTDDI_WINTHRESHOLD                  0x0A000000  /* ABRACADABRA_THRESHOLD */
#define NTDDI_WIN10                         0x0A000000  /* ABRACADABRA_THRESHOLD */
#define NTDDI_WIN10_TH2                     0x0A000001  /* ABRACADABRA_WIN10_TH2 */
#define NTDDI_WIN10_RS1                     0x0A000002  /* ABRACADABRA_WIN10_RS1 */
#define NTDDI_WIN10_RS2                     0x0A000003  /* ABRACADABRA_WIN10_RS2 */
#define NTDDI_WIN10_RS3                     0x0A000004  /* ABRACADABRA_WIN10_RS3 */
#define NTDDI_WIN10_RS4                     0x0A000005  /* ABRACADABRA_WIN10_RS4 */

#define WDK_NTDDI_VERSION                   NTDDI_WIN10_RS4 /* ABRACADABRA_WIN10_RS4 */


//
// masks for version macros
//
#define OSVERSION_MASK      0xFFFF0000
#define SPVERSION_MASK      0x0000FF00
#define SUBVERSION_MASK     0x000000FF


//
// macros to extract various version fields from the NTDDI version
//
#define OSVER(Version)  ((Version) & OSVERSION_MASK)
#define SPVER(Version)  (((Version) & SPVERSION_MASK) >> 8)
#define SUBVER(Version) (((Version) & SUBVERSION_MASK) )


#if defined(DECLSPEC_DEPRECATED_DDK)

// deprecate in 2k or later
#if (NTDDI_VERSION >= NTDDI_WIN2K)
#define DECLSPEC_DEPRECATED_DDK_WIN2K DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WIN2K
#endif

// deprecate in XP or later
#if (NTDDI_VERSION >= NTDDI_WINXP)
#define DECLSPEC_DEPRECATED_DDK_WINXP DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WINXP
#endif

// deprecate in WS03 or later
#if (NTDDI_VERSION >= NTDDI_WS03)
#define DECLSPEC_DEPRECATED_DDK_WIN2003 DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WIN2003
#endif

// deprecate in WIN6 or later
#if (NTDDI_VERSION >= NTDDI_WIN6)
#define DECLSPEC_DEPRECATED_DDK_WIN6 DECLSPEC_DEPRECATED_DDK
#else
#define DECLSPEC_DEPRECATED_DDK_WIN6
#endif

#define DECLSPEC_DEPRECATED_DDK_LONGHORN DECLSPEC_DEPRECATED_DDK_WIN6

#endif // defined(DECLSPEC_DEPRECATED_DDK)


//
// if versions aren't already defined, default to most current
//

#define NTDDI_VERSION_FROM_WIN32_WINNT2(ver)    ver##0000
#define NTDDI_VERSION_FROM_WIN32_WINNT(ver)     NTDDI_VERSION_FROM_WIN32_WINNT2(ver)

#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
#define  _WIN32_WINNT   0x0A00
#endif

#ifndef NTDDI_VERSION
#ifdef _WIN32_WINNT
#if (_WIN32_WINNT <= _WIN32_WINNT_WINBLUE)
// set NTDDI_VERSION based on _WIN32_WINNT
#define NTDDI_VERSION   NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
#elif (_WIN32_WINNT >= _WIN32_WINNT_WIN10)
// set NTDDI_VERSION to default to WDK_NTDDI_VERSION
#define NTDDI_VERSION   WDK_NTDDI_VERSION 
#endif // (_WIN32_WINNT <= _WIN32_WINNT_WINBLUE)
#else
// set NTDDI_VERSION to default to latest if _WIN32_WINNT isn't set
#define NTDDI_VERSION   0x0A000005
#endif // _WIN32_WINNT
#endif // NTDDI_VERSION

#ifndef WINVER
#ifdef _WIN32_WINNT
// set WINVER based on _WIN32_WINNT
#define WINVER          _WIN32_WINNT
#else
#define WINVER          0x0A00
#endif
#endif

#ifndef _WIN32_IE
#ifdef _WIN32_WINNT
// set _WIN32_IE based on _WIN32_WINNT
#if (_WIN32_WINNT <= _WIN32_WINNT_NT4)
#define _WIN32_IE       _WIN32_IE_IE50
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN2K)
#define _WIN32_IE       _WIN32_IE_IE501
#elif (_WIN32_WINNT <= _WIN32_WINNT_WINXP)
#define _WIN32_IE       _WIN32_IE_IE60
#elif (_WIN32_WINNT <= _WIN32_WINNT_WS03)
#define _WIN32_IE       _WIN32_IE_WS03
#elif (_WIN32_WINNT <= _WIN32_WINNT_VISTA)
#define _WIN32_IE       _WIN32_IE_LONGHORN
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN7)
#define _WIN32_IE       _WIN32_IE_WIN7
#elif (_WIN32_WINNT <= _WIN32_WINNT_WIN8)
#define _WIN32_IE       _WIN32_IE_WIN8
#else
#define _WIN32_IE       0x0A00
#endif
#else
#define _WIN32_IE       0x0A00
#endif
#endif

//
// Sanity check for compatible versions
//
#if defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(RC_INVOKED)

#if (defined(WINVER) && (WINVER < 0x0400) && (_WIN32_WINNT > 0x0400))
#error WINVER setting conflicts with _WIN32_WINNT setting
#endif

#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WIN2K) && (_WIN32_WINNT != _WIN32_WINNT_WIN2K))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif

#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WINXP) && (_WIN32_WINNT != _WIN32_WINNT_WINXP))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif

#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_WS03) && (_WIN32_WINNT != _WIN32_WINNT_WS03))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif

#if (((OSVERSION_MASK & NTDDI_VERSION) == NTDDI_VISTA) && (_WIN32_WINNT != _WIN32_WINNT_VISTA))
#error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting
#endif

#if ((_WIN32_WINNT < _WIN32_WINNT_WIN2K) && (_WIN32_IE > _WIN32_IE_IE60SP1))
#error _WIN32_WINNT settings conflicts with _WIN32_IE setting
#endif

#endif  // defined(_WIN32_WINNT) && !defined(MIDL_PASS) && !defined(_WINRESRC_)

#if (_MSC_VER >= 800)
#if (_MSC_VER >= 1200)
#pragma warning(pop)
#else
#pragma warning(default:4001) /* nonstandard extension : single line comment */
#endif
#endif

#endif  /* !_INC_SDKDDKVER */
To emphasize that the implementation is ANSI C, the one and only source file is StrfTime_Token_Demo.C.

Points of Interest

Though the program is as straightforward as its task, there are a few notwworthy items, starting with the preprocessor symbol definitions that immediately follow the CRT library headers.

// ----------------------------------------------------------------------------
// Define custom preprocessor symbols used by this module.
// ----------------------------------------------------------------------------

#define ARRAY_FIRAT_ELEMENT_SUBSCRIPT 0
#define ARRAY_INVALID_SUBSCRIPT   -1
#define ARRAY_ORDINAL_FROM_SUBSCRIPT 1

#define CONSOLE_INPUT_BUFFER_SIZE       100

#define CRT_TIME_ERROR                  -1
#define CRT_TIME_CONVERSION_ERROR  0

#define OUTPUT_FILENAME     L"StrfTime_Token_Demo.TSV"

#define STRFTIME_DEFAULT_FORMAT   L"%Y/%m/%d %H:%M:%S %Z"
#define STRFTIME_OUTBUF_SIZE   64
#define STRFTIME_OUTPUT_MAX_CHARS_OUT ( STRFTIME_OUTBUF_SIZE - 1 )

#define RETCODE_SUCCESS                 0
#define RETCODE_STRFTIME_ERROR   255

If a literal appears more than once or its meaning depends on its context, it gets a preprocessor macro.

// ----------------------------------------------------------------------------
// Bake this array of strftime token strings into the code.
// ----------------------------------------------------------------------------

const wchar_t * m_alpszRawFormatStrings [ ] = {
 L"%a" ,
 L"%A" ,
 L"%b" ,
 L"%B" ,
 L"%c" ,
 L"%d" ,
 L"%H" ,
 L"%I" ,
 L"%j" ,
 L"%m" ,
 L"%M" ,
 L"%p" ,
 L"%S" ,
 L"%U" ,
 L"%W" ,
 L"%w" ,
 L"%x" ,
 L"%X" ,
 L"%y" ,
 L"%Y" ,
 L"%z" ,
 L"%Z" ,
 L"%%" };

// ----------------------------------------------------------------------------
// Bake this array of modified strftime token strings into the code.
// ----------------------------------------------------------------------------

const wchar_t * m_alpszModifiedFormatStrings [ ] = {
 L"%#a" ,
 L"%#A" ,
 L"%#b" ,
 L"%#B" ,
 L"%#c" ,
 L"%#d" ,
 L"%#H" ,
 L"%#I" ,
 L"%#j" ,
 L"%#m" ,
 L"%#M" ,
 L"%#p" ,
 L"%#S" ,
 L"%#U" ,
 L"%#W" ,
 L"%#w" ,
 L"%#x" ,
 L"%#X" ,
 L"%#y" ,
 L"%#Y" ,
 L"%#z" ,
 L"%#Z" ,
 L"%#%" };

const wchar_t * m_alpszFormatDescriptions [ ] = {
 L"Abbreviated weekday name" ,
 L"Full weekday name" ,
 L"Abbreviated month name" ,
 L"Full month nam" ,
 L"Date and time representation appropriate for locale" ,
 L"Day of month as decimal number (01 – 31)" ,
 L"Hour in 24-hour format (00 – 23)" ,
 L"Hour in 12-hour format (01 – 12)" ,
 L"Day of year as decimal number (001 – 366)" ,
 L"Month as decimal number (01 – 12)" ,
 L"Minute as decimal number (00 – 59)" ,
 L"Current locale's A.M./P.M. indicator for 12-hour clock" ,
 L"Second as decimal number (00 – 59)" ,
 L"Week of year as decimal number, with Sunday as first day of week (00 – 53)" ,
 L"Week of year as decimal number, with Monday as first day of week (00 – 53)" ,
 L"Weekday as decimal number (0 – 6; Sunday is 0)" ,
 L"Date representation for current locale" ,
 L"Time representation for current locale" ,
 L"Year without century, as decimal number (00 – 99)" ,
 L"Year with century, as decimal number" ,
 L"Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown" ,
 L"Either the time-zone name or time zone abbreviation, depending on registry settings; no characters if time zone is unknown" ,
 L"Percent sign (The doubled percent sign behaves in the standard way to suppress the default intepretation of the % character.)" };

The foregoing three arrays could easily have been organized into a single multi-dimensional array, but it was simpler to keep them separate, since all three are processed by the same loop, which uses the same index as the subscript for all three.

Finally, all buffers are defined at module scope, so that they get baked into the code, which gets them initialized by the compiler, and has no effect on the memory footprint of the program, since all are used for its entire lifetime.

History

Wednesday, 20 June 2018, this article was submitted for publication.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here