Click here to Skip to main content
15,886,831 members
Articles / Programming Languages / C
Reference

strftime Substitution Token Viewer

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
20 Jun 2018CPOL3 min read 7.4K   38   2   4
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.

C++
#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.

C++
/*

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.

C++
// ----------------------------------------------------------------------------
// 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.

C++
// ----------------------------------------------------------------------------
// 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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I deliver robust, clean, adaptable, future-ready applications that are properly documented for users and maintainers. I have deep knowledge in multiple technologies and broad familiarity with computer and software technologies of yesterday, today, and tomorrow.

While it isn't perceived as sexy, my focus has always been the back end of the application stack, where data arrives from a multitude of sources, and is converted into reports that express my interpretation of The Fundamental Principle of Tabular Reporting, and are the most visible aspect of the system to senior executives who approve the projects and sign the checks.

While I can design a front end, I prefer to work at the back end, getting data into the system from outside sources, such as other computers, electronic sensors, and so forth, and getting it out of the system, as reports to IDENTIFY and SOLVE problems.

When presented with a problem, I focus on identifying and solving the root problem for the long term.

Specialties: Design: Relational data base design, focusing on reporting; organization and presentation of large document collections such as MSDS libraries

Development: Powerful, imaginative utility programs and scripts for automated systems management and maintenance

Industries: Property management, Employee Health and Safety, Services

Languages: C#, C++, C, Python, VBA, Visual Basic, Perl, WinBatch, SQL, XML, HTML, Javascript

Outside Interests: Great music (mostly, but by no means limited to, classical), viewing and photographing sunsets and clouds, traveling by car on small country roads, attending museum exhibits (fine art, history, science, technology), long walks, especially where there is little or no motor traffic, reading, especially nonfiction and thoughtfully written, thought provoking science fiction

Comments and Discussions

 
GeneralSimpler? Pin
Rick York21-Jun-18 6:13
mveRick York21-Jun-18 6:13 
GeneralRe: Simpler? Pin
David A. Gray21-Jun-18 6:43
David A. Gray21-Jun-18 6:43 
GeneralRe: Simpler? Pin
Rick York21-Jun-18 15:09
mveRick York21-Jun-18 15:09 
GeneralRe: Simpler? Pin
David A. Gray22-Jun-18 8:02
David A. Gray22-Jun-18 8:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.