---
title: 日付の形式を変更する
tags:  #[第11回大阪sas勉強会]  
author: [森岡裕[SASユーザー総会世話人]](https://www.docswell.com/user/6484025)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/8JDLQKV37G.jpg?width=480
description: [第11回大阪sas勉強会]
published: April 15, 25
canonical: https://www.docswell.com/s/6484025/KV1ELJ-2025-04-15-050539
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/8JDLQKV37G.jpg)

日付の形式を変更する
エイツーヘルスケア株式会社
淺井友紀


# Page. 2

![Page Image](https://bcdn.docswell.com/page/VEP2LKVPE8.jpg)

日付の形式を変換したい
• dd/mmm/yyyy形式の日付の文字値を、yyyy-mm-dd形式の日付
の文字値に変換するマクロの紹介です。
• 動作例 (UN/UNKは詳細不明だけど文字が入ってきているものとしま
す。 UN/UNKに限らず、日付としてあり得ない入力は詳細不明として
マクロ内で扱います)
• 01/Jan/2023 -&gt; 2023-01-01
• UN/Jan/2023-&gt;2023-01
• UN/UNK/2023-&gt;2023
• UN/2023-&gt;2023
• 01/Jan-&gt; --01-01
• 01/UNK/2023-&gt;2023---01


# Page. 3

![Page Image](https://bcdn.docswell.com/page/27VDQVZV7Q.jpg)

マクロのパラメータ
• %ST_DTC_DDMMMYYYY(
_indt = 入力する日付変数(文字値 dd/mmm/yyyy形式),
_outdt = 出力する日付変数(文字値 yyyy-mm-dd形式),
_delim= 入力日付変数の区切り文字*
);
*区切り文字は”で挟んで指定する(区切り文字がスペースの時に
対応するため)
*区切り文字は統一されてないとマクロが正しく実行されない


# Page. 4

![Page Image](https://bcdn.docswell.com/page/5JGYWL41JL.jpg)

マクロ内でやっていること
• 入力日付の区切り文字をスラッシュに置換
• V_DLIM_DATE = transtrn(strip(&amp;_indt.) , &amp;_delim., &quot;/&quot;) ;
• 年月日の要素で不足している個所を”--”で補完
• Jun/2023-&gt;--/Jun/2023, 01/Jun-&gt;01/Jun/----, 01//2023-&gt;01/-/2023
• 欠測として入っている要素を”--”に置換
• 日付をdd/mmm/yyyyからyyyy-mm-ddに変換


# Page. 5

![Page Image](https://bcdn.docswell.com/page/47QM3YGNEP.jpg)

マクロ内でやっていること
• 欠測として入っている要素を”--”に置換
• UN/Jun/2023-&gt;--/Jun/2023, 05/UNK/9999-&gt;05/--/---• 様々ある「欠測として入っている文字」を拾うため正規表現を使用
• if prxmatch( &quot;/0[1-9]|[1-9]|[1-2][0-9]|3[0-1]/&quot; , strip(V_PRT_DATE) ) = 0 then
V_PRT_DATE = &quot;--&quot; ;
• if prxmatch(“/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/” ,
strip(upcase(V_PRT_MONTH)) )=0 then V_PRT_MONTH = “--” ;
• if prxmatch( &quot;/(?!9999)¥d{4}/&quot; , strip(V_PRT_YEAR) ) = 0 then V_PRT_YEAR = &quot;---&quot; ;
• 日付けならUNや99、35等が欠測扱い、月はアルファベット以外を欠測、年
は数字4桁以外と9999を欠測扱いとしている
• 月と日の欠測を区別するために、日付が”--”なら”@--”と識別用の文字を付加
• @--/--/2025
• こんな要素ごとに分岐や、識別用の@の付加をせずとも、prxchangeで置換
できると思うのですがうまくいかず…正規表現って難しい…


# Page. 6

![Page Image](https://bcdn.docswell.com/page/KE4V1W5371.jpg)

マクロ内でやっていること
• dd/mmm/yyyyをyyyy/mm/ddに変換
• この時点で足りない要素を”--”で補完して、日付であり得ない入力を”-”に置き換えているので、--/Jan/2023や、05/--/2023等の形になっ
ている
• -が無ければ形式を変換
• &amp;_outdt. = put(input(V_DT, ??date11.), yymmdd10.) ;
• 日のみが欠測なら年月のみ変換 (--/Jan/2023)
• if index(V_PRE_CONV, &quot;@--&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/--/&quot;) = 0 and
index(V_PRE_CONV, &quot;/----&quot;) = 0 then z = put(input( transtrn(V_PRE_CONV,
&quot;@--/&quot;, trimn(&quot;&quot;)), ??monyy8.), yymmd.) ;
• 月日が欠測なら年のみ変換
• --/--/2023 -&gt; 2023
他のパターンも変換していますが資料では省略します…


# Page. 7

![Page Image](https://bcdn.docswell.com/page/L713GYWZEG.jpg)

出来ない事
• 2月の考慮
• 正規表現で0[1-9]|[1-9]|[1-2][0-9]|3[0-1]としているので、2/30等は欠測に
なります
• うるう年ではないときに2/29が来ても同様に欠測になります
• そこまでを検知する分岐はちょっと諦めました…
• 処理イメージ
• data _null_ ;
• a = &quot;30/feb/2025&quot; ;
• b = put(input(a, ??date11.), yymmdd10.) ;
• putlog a = b = ;
• run ;
• log
• a=30/feb/2025 b=.


# Page. 8

![Page Image](https://bcdn.docswell.com/page/G7WPKG66E2.jpg)

%macro ST_DTC_DDMMYYYY(_indt = ,_outdt = , _delim= ) ;
/*----_indt : store character value date ex: raw data date with ddmmmyy
_outdt : Character variable name to output with yyyy/mm/dd format
_delim : year, month, date separator
Only _delim should be enclosed in double-cotation marks. ex : &quot; &quot; or &quot;-&quot;
-----*/
V_DLIM_DATE = transtrn(strip(&amp;_indt.) , &amp;_delim., &quot;/&quot;) ;
/*&gt;&gt;&gt;&gt;&gt;---------- Fill in the missing elements with -- ----------&lt;&lt;&lt;&lt;&lt;*/
length V_INDT_FILL $20 ;
if count(V_DLIM_DATE, &quot;/&quot;) = 2 then do ;
if first(V_DLIM_DATE) = &quot;/&quot; then V_INDT_FILL = cats(&quot;--&quot;, V_DLIM_DATE) ;
else if index(V_DLIM_DATE,&quot;//&quot;) then V_INDT_FILL = transtrn(V_DLIM_DATE, &quot;//&quot;, &quot;/--/&quot;) ;
else if first(reverse( strip(V_DLIM_DATE) )) = &quot;/&quot; then V_INDT_FILL = cats(V_DLIM_DATE, &quot;----&quot;) ;
else V_INDT_FILL = V_DLIM_DATE ;
end ;
if count(V_DLIM_DATE,&quot;/&quot;) = 1 then do ;
if prxmatch( &quot;/\d{4}$/&quot;, strip(V_DLIM_DATE) ) = 0 then V_INDT_FILL = cats(V_DLIM_DATE,&quot;/----&quot;) ;
if prxmatch( &quot;/\d{4}$/&quot;, strip(V_DLIM_DATE) ) &gt; 0 then V_INDT_FILL = cats( &quot;--/&quot; , V_DLIM_DATE) ;
end ;
if count(V_DLIM_DATE , &quot;/&quot;) = 0 then do ;
if prxmatch( &quot;/\d{4}/&quot;, strip(V_DLIM_DATE) ) &gt; 0 then V_INDT_FILL = cats(&quot;--/--/&quot; ,V_DLIM_DATE) ;
else if prxmatch( &quot;/\d{2}/&quot;, strip(V_DLIM_DATE) ) &gt; 0 then V_INDT_FILL = cats( V_DLIM_DATE, &quot;/--/----&quot; ) ;
else if prxmatch( &quot;/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/&quot;, strip(upcase(V_DLIM_DATE)) ) &gt; 0 then V_INDT_FILL = cats(&quot;--/&quot; , V
_DLIM_DATE, &quot;/----&quot; ) ;
else call missing(V_INDT_FILL) ;
end ;
/*&gt;&gt;&gt;&gt;&gt;---------- Replace non-date value with -- ----------&lt;&lt;&lt;&lt;&lt;*/
length V_PRT_DATE V_PRT_MONTH V_PRT_YEAR $8 ;
V_PRT_DATE = scan(V_INDT_FILL, 1, &quot;/&quot;) ;
V_PRT_MONTH = scan(V_INDT_FILL, 2, &quot;/&quot;) ;
V_PRT_YEAR = scan(V_INDT_FILL, 3, &quot;/&quot;) ;
if prxmatch( &quot;/0[1-9]|[1-9]|[1-2][0-9]|3[0-1]/&quot;
, strip(V_PRT_DATE) )
= 0 then V_PRT_DATE = &quot;--&quot; ;
if prxmatch( &quot;/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/&quot; , strip(upcase(V_PRT_MONTH)) ) = 0 then V_PRT_MONTH = &quot;--&quot; ;
if prxmatch( &quot;/(?!9999)\d{4}/&quot;
, strip(V_PRT_YEAR) )
= 0 then V_PRT_YEAR = &quot;----&quot; ;
/*&gt;&gt;&gt;&gt;&gt;---------- after replace date ----------&lt;&lt;&lt;&lt;&lt;*/
length V_PRE_CONV $20 ;
V_PRE_CONV = cats(V_PRT_DATE, &quot;/&quot;, V_PRT_MONTH, &quot;/&quot;, V_PRT_YEAR ) ;
if first(strip(V_PRE_CONV)) = &quot;-&quot; then V_PRE_CONV = cats(&quot;@&quot;, V_PRE_CONV) ;
/*&gt;&gt;&gt;&gt;&gt;---------- convet ddmmmyyy to yyyymmdd ----------&lt;&lt;&lt;&lt;&lt;*/
/*---------- complete date ----------*/
length &amp;_outdt. $20 ;
if index(V_PRE_CONV, &quot;--&quot;) = 0 then &amp;_outdt. = put(input(V_PRE_CONV, ??date11.), yymmdd10.) ;
/*---------- one missing part ----------*/
if index(V_PRE_CONV, &quot;@--&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/--/&quot;) = 0 and index(V_PRE_CONV, &quot;/----&quot;) = 0 then z = put(input( transtrn(V_PRE_CONV, &quot;
@--/&quot;, trimn(&quot;&quot;)), ??monyy8.), yymmd.) ;
if index(V_PRE_CONV, &quot;@--&quot;) = 0 and index(V_PRE_CONV, &quot;/--/&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/----&quot;) = 0 then do ;
&amp;_outdt. = cats( transtrn(put(input(transtrn(V_PRE_CONV, &quot;/--/&quot;, &quot;/Jan/&quot;), ??date11.), yymmdd10.) , &quot;-01-&quot; , &quot;---&quot;) ) ;
end ;


# Page. 9

![Page Image](https://bcdn.docswell.com/page/4JZKZLYRJ3.jpg)

if index(V_PRE_CONV, &quot;@--&quot;) = 0 and index(V_PRE_CONV, &quot;/--/&quot;) = 0 and index(V_PRE_CONV, &quot;/----&quot;) &gt; 0 then do ;
&amp;_outdt. = cats( transtrn(put(input(transtrn(V_PRE_CONV, &quot;/----&quot;, &quot;2020&quot; ), ??date11.), yymmdd10.), &quot;2020&quot;, &quot;-&quot;) ) ;
end ;
/*---------- two missing part ----------*/
if index(V_PRE_CONV, &quot;@--&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/--/&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/----&quot;) = 0 then &amp;_outdt. = scan(V_PRE_CONV, 3, &quot;/&quot; )
;
if index(V_PRE_CONV, &quot;@--&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/--/&quot;) = 0 and index(V_PRE_CONV, &quot;/----&quot;) &gt; 0 then do ;
&amp;_outdt. = strip(put(input(transtrn(transtrn(V_PRE_CONV, &quot;@--&quot;, &quot;01&quot;) , &quot;/----&quot;, &quot;2020&quot;), ??date11.) , yymmdd10.)) ;
&amp;_outdt. = transtrn(transtrn(&amp;_outdt., &quot;2020&quot;, &quot;-&quot;), &quot;-01&quot;, &quot;--&quot;) ;
end ;
if index(V_PRE_CONV, &quot;@--&quot;) = 0 and index(V_PRE_CONV, &quot;/--/&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/----&quot;) &gt; 0 then do ;
&amp;_outdt. = strip(put(input(transtrn(transtrn(V_PRE_CONV, &quot;/--/&quot;, &quot;/Jan/&quot;) , &quot;/----&quot;, &quot;2020&quot;), ??date11.) , yymmdd10.)) ;
&amp;_outdt. = transtrn(transtrn(&amp;_outdt., &quot;2020&quot;, &quot;-&quot;), &quot;-01-&quot;, &quot;---&quot;) ;
end ;
/*&gt;&gt;&gt;&gt;&gt;---------- three missing part ------&lt;&lt;&lt;&lt;&lt;*/
if index(V_PRE_CONV, &quot;@--&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/--/&quot;) &gt; 0 and index(V_PRE_CONV, &quot;/----&quot;) &gt; 0 then call missing(&amp;_outdt.) ;
if missing(V_PRE_CONV) = 1 then call missing(&amp;_outdt.) ;
%mend ST_DTC_DDMMYYYY ;


