惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
G
Google Developers Blog
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
博客园 - Franky
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
WordPress大学
WordPress大学
有赞技术团队
有赞技术团队
月光博客
月光博客
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
Microsoft Security Blog
Microsoft Security Blog
Last Week in AI
Last Week in AI
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
J
Java Code Geeks
博客园 - 叶小钗
Engineering at Meta
Engineering at Meta
阮一峰的网络日志
阮一峰的网络日志

IT Jungle

Finally: Some Pricing Information On The Power S1112 Entry Server - IT Jungle Rocket Automates Manual IBM i Tasks With AI - IT Jungle Guru: Where’s The Table? - IT Jungle LaserVault Goes iSCSI With Virtual Tape Library - IT Jungle IBM i PTF Guide, Volume 28, Number 31 - IT Jungle Will Power Chips Get A Converged Arm Instruction Set Like Z Mainframe CPUs? - IT Jungle Thinking About Moving IBM i To The Cloud? Don't Start With The Quote - IT Jungle Precisely To Add Ransomware Protection In MIMIX 11 - IT Jungle It’s D-Day For Cybersecurity, AI Firms Warn - IT Jungle IBM i PTF Guide, Volume 28, Number 30 - IT Jungle Oracle Dips A Toe Into IBM’s EBCDIC World - IT Jungle When Your Small IBM i Team Is Really A Team Of One - IT Jungle Guru: Putting Failure Handling In Its Place - IT Jungle Inside The Security Enhancements In ACS - IT Jungle IBM i PTF Guide, Volume 28, Number 28: A Crazy Number of Security Vulnerability Patches - IT Jungle IBM i PTF Guide, Volume 28, Number 29 - IT Jungle IBM i PTF Guide, Volume 28, Number 28: A Crazy Number of Security Vulnerability Patches - IT Jungle Inside The Encryption Key Management Changes In IBM i 7.6 - IT Jungle FalconStor Moved To The Blue Lagoon, And Is Poised For Growth Because Of It - IT Jungle Guru: Claude’s SQL Tip - IT Jungle Astera Makes Extracting Legacy Report Data an AI Specialty - IT Jungle IBM i PTF Guide, Volume 28, Number 27 - IT Jungle Welcoming The New IBM i Chief Architect And Other New Top Brass - IT Jungle A Deep Dive Into That Power S1112 Entry Power11 Server - IT Jungle Guru: Beyond Three-Part Naming – Running SQL Across Remote IBM i Systems - IT Jungle How IBM Bolstered IBM i Resilience In The Summer Tech Refreshes - IT Jungle IBM i PTF Guide, Volume 28, Number 26 - IT Jungle Power Systems Has A Great Quarter; System Z, Not So Much - IT Jungle Does AI Mark The End Of The ERP Era? - IT Jungle Guru: Deterministic Application Development With AI - IT Jungle
Guru: DateTime Rules Of Thumb - IT Jungle
Ted Holt · 2026-05-18 · via IT Jungle

May 18, 2026

I am not a great programmer. I am a decent programmer who has found ways to stay out of trouble. I use many little rules of thumb to keep me and the people I serve from being unpleasantly surprised at inopportune moments. Today I share rules of thumb regarding datetime data that have served me in my work.

The first date field I used in an RPG program was a six-digit zoned-decimal value in MMDDYY format. This was part of a programming assignment for a class I was taking at the local vocational-technical center in days of yore. In my nascent understanding of Data Processing, this is how dates were stored in the file system.

After a few years on the job I tired of the problems this date format continually presented me, especially when using the #GSORT system utility to select and sort records from S/36 files. I wised up and started storing dates in YYMMDD format. (Y2K was still several years into the future.)

In the decades since, I have seen datetime data stored in many formats, but as far as I’m concerned, the only proper ways to store transactional datetime data these days is in DATE and TIMESTAMP columns of tables defined with SQL.

“What about the TIME data type?” I hear you asking. The only proper application for standalone TIME columns of which I’m aware is in a recurring schedule, such as a timetable for trains or flights. I’m sure there are other uses. I don’t think I’ve ever defined a TIME column in a table definition for production work.

If a time is associated with a date, I recommend a TIMESTAMP column, not separate DATE and TIME columns. It makes sense to me to define a single TIMESTAMP column because date and time together represent a single point in history, but it also facilitates row selection

For instance, suppose you want to select all rows from 6:00 PM of one day through 6:00 AM of the next day. If date and time are in separate columns, you have to use the TIMESTAMP function to combine them, like this:

select * from SomeTable as t
 where timestamp(t.DateCreated, t.TimeCreated) 
 between '2026-07-04-18.00.00' and '2026-07-05-06.00.00';

I admire TIMESTAMP’s ability to combine a date and time, an ability I wish RPG’s %TIMESTAMP function had. However, I avoid placing a function on the left side of a row selection expression, as it often degrades performance. If DateCreated and TimeCreated were one WhenCreated column, I wouldn’t need the TIMESTAMP function.

select * from SomeTable as t
 where t.WhenCreated
 between '2026-07-04-18.00.00' and '2026-07-05-06.00.00'; 

So we’re left with the DATE and TIMESTAMP data types for most applications. DATE usually suffices. Doctors, taxing authorities, banks and other usurious financial institutions, my kids, and cyber-terrorists the world over all know the date of my birth, but no one has ever asked me what time I was born. When time is irrelevant, I recommend using a DATE column.

That leaves TIMESTAMP. By default, I recommend TIMESTAMP(0), as fractions of a second are not usually required. TIMESTAMP without an argument defines a column with 6 fractional positions (microseconds). If you need them, you can define up to 12 fractional positions.

Fractions of a second are good if you need them, but they can mess up a query when they’re there only because someone didn’t have the foresight to leave them off. Assume this data set:

Key   WhenCreated
---   --------------------------
1     2026-07-04 08:00:00.123456
2     2026-07-04 08:00:35.222446
3     2026-07-04 08:01:10.306599
4     2026-07-04 08:23:59.000000
5     2026-07-04 08:23:59.227751
6     2026-07-04 08:23:59.999999

Which rows get returned by the following query?

select * from SomeTable
 where WhenCreated 
  between '2026-07-04-08.01.00' and '2026-07-04-08.23.59'

The answer, of course, is that the query returns rows 3 and 4. The microseconds eliminated rows 5 and 6. Chances of this type of query returning an inaccurate result set are slim, but I do my best not to leave anything to chance.

If you’re stuck querying a timestamp with fractions of a second, you have at least two workarounds. You can include fractions of seconds in the right side of the expression, like this:

select * from SomeTable
 where WhenCreated
  between '2026-07-04-08.01.00.000000'
      and '2026-07-04-08.23.59.999999';

Or you can use the Truncate timestamp (TRUNC_TIMESTAMP ) function on the left side of the expression.

select * from SomeTable
 where trunc_timestamp(WhenCreated, 'SS')
  between '2026-07-04-08.01.00'
      and '2026-07-04-08.23.59';

Yes, I put a function on the left side of the expression. I avoid it, but I do it when I have to.

TRUNC_TIMESTAMP can be used to select to any degree of precision. The previous example truncated everything past seconds (“SS”). Here’s one way to get all orders for a month, in this case July of 2026.

select * from qtemp.temp01
 where trunc_timestamp(WhenCreated, 'MM') = '2026-07-01';

TRUNC_TIMESTAMP sets everything past the degree of precision to low values, which means 01 for month and day, and zeros for all portions of the time, including fractions of a second. I did not have to specify the time portion of the datetime literal value because the default of the time portion of a timestamp is all zeros.

A similar function, ROUND_TIMESTAMP, rounds to the nearest units according to the precision required. For instance, rounding to the minute treats seconds values of 30 or more as part of the next minute.

If needed, you can use other functions on the left side of the row-selection expression.

select . . . where date(WhenCreated) = '2026-07-04';
select . . . where time(WhenCreated) = '08.00.00';
select . . . where year(WhenCreated) = 2026;
select . . . where month(WhenCreated) = 7;
select . . . where day(WhenCreated) = 5;
select . . . where hour(WhenCreated) = 12;
select . . . where minute(WhenCreated) = 23;
select . . . where second(WhenCreated) = 59;
select . . . where microsecond(WhenCreated) = 227751;

I might summarize these rules of thumb thus:

1: Use SQL, not DDS, to define physical files.

2: Use DATE if time is irrelevant.

3: Use one TIMESTAMP column, not separate DATE and TIME columns, for a single point in time.

4: Define timestamps as TIMESTAMP(0) by default. Use fractions of seconds only when required.

I still work with database files that store dates and times in alpha and numeric fields, but my preference by far is to use the datetime data types, mainly because the system rejects invalid date and time values. Strong data types promote database integrity.

Ted Holt is the original, the one and only, chief of the Four Hundred Gurus. We are glad he is back with us writing technical material that helps IBM i programmers. He is a self-employed, independent programmer living near Tupelo, Mississippi, who is old enough to retire but is not ready to do so. He still enjoys programming and is available to help others as needed. He welcomes your comments, questions, and suggestions.

RELATED STORIES

Guru: Load A Varying-Dimension Array With One SQL Fetch

The Four Hundred Guru Retires

Guru: Dynamic Arrays Come To RPG

Guru: Dynamic Arrays Come To RPG – The Next Part Of The Story

Guru: Dynamic Arrays Come To RPG – Limitations, Circumventions, And More

Guru: Global Variables in Modules

Guru: Assertions, Take 2

Guru: Using Mixed Lists To Add “Data Structures” To CL Commands

Guru: TryIT – You’ll Like It

Guru: Aliases — Underused and Unappreciated

Guru: Beware of SQL Precompiler Variables

Guru: The SND-MSG Op Code And Message Subfiles

Guru: The CALL I’ve Been Waiting For

The Four Hundred Guru Retires

Guru: Global Variables in Modules

Guru: Abstract Data Types and RPG

Guru: Flexible Interfaces

Guru: Quick And Handy RPG Output, Take 2

Guru: What Is Constant Folding And Why Should I Care About It?

Guru: Alternate SQL Row-Selection Criteria Revisited Revisited

Guru: Another Red Flag – Joining On Expressions

Guru: Set Beats A Loop

Guru: The Deception of Fractional Labeled Durations

Guru: Elapsed Time For Human Beings

Guru: One-Shot Requests and Quoted Column Names

Guru: Use SQL To Replace Reports

Guru: Date Format Confusion

Guru: Compare Pieces Of Source Members

Guru: Stub Testing And SQL

Guru: QCMDEXC Makes A Good CPP

Guru: SELECT INTO And Arrays

Guru: I’m A Number, You’re A Number, Everybody’s A Number

Guru: SQL PL, WHILE And REPEAT Loops