2026年1月30日金曜日

日時のシリアル値をタイムゾーンのオフセットありの書式へ変換するマクロ

タイムゾーンを指定して日時の書式を設定

タイムゾーンを指定して E8601DXの書式でフォーマットするマクロです。入力は日時のシリアル値、結果は macvar で指定した変数に返ります。

  • 入力のパラメータ DT=2085402932.92693, TZ='America/New_York'
  • 結果 2026-01-30T00:35:33-05:00
SASシステムオプションでTZ変えて書式整えれば良いのですが、システム的に変更を禁止されている場合があります。あと、なんかテストしていて正しく書式が定義されないので自分でロジックを組んでしまったのです。
最近この日時の書式を使うようにしています。理由は海外のエンジニアにログとかメトリクスの抽出を依頼するときに、タイムゾーンがはっきりと分かる方が便利だからです。

作成したマクロ  


%macro formatSerialDateTime(dt=, tz=, macvar=, debug=0);
  %let &macvar=;
  %local notes tmp;

  /* Suppress NOTE logs */ 
  %let notes=%sysfunc(getoption(notes));
  options nonotes;
  
  /* Set default value */
  %if %length(&dt)=0 %then %let dt=%sysfunc(datetime());
  
  %let tmp=; 
  data _null_;
    attrib result length=$64;
    attrib dt length=8 label='datetime';
    attrib tz length=$32 label='timezone';
    attrib offset1 length=8 label='Default offset';
    attrib offset2 length=8 label='Time zone offset specified by the parameter';

    /* Remove quotation marks from parameters */    
    dt = dequote(symget('dt'));
    tz = dequote(symget('tz'));
 
    /* Calculate the offset time according to the time zone */
    offset1 = tzoneoff();
    if missing(tz) then offset2 = offset2;
    else offset2 = tzoneoff(tz);
    
    /* Once the time zone is correctly obtained, set the date and time. */
    if not missing(offset2) then do;
    
      dt = dt + (offset2 - offset1);
  
      /* Set the offset sign */    
      if offset2<0 then sign= "-";
      else sign="+";
      
      /* Construct the result string and set it to the macro variable. */
      length year month day hour minute second hh mm 8;
      length offset $8;
      year = year(datepart(dt));
      month = month(datepart(dt));
      day = day(datepart(dt));
      hour = hour(dt);
      minute = minute(dt);
      second = second(dt);
      hh = hour(abs(offset2));
      mm = minute(abs(offset2));
      
      ymd = cats(put(year,z4.), '-', put(month, z2.), '-', put(day,z2.));
      hms = cats(put(hour,z2.), ':', put(minute,z2.), ':', put(second,z2.));
      offset = cats(sign, put(hh,z2.), ':', put(mm,z2.));
      
      result = cats(ymd, 'T', hms, offset);
    end;
    
    call symputx('tmp', compress(result));
  run;  
  %if &syserr=0 %then %let &macvar=&tmp;

  options ¬es;
  %if &debug=1 %then %put DEBUG: formatSerialDateTime(&=dt, &=tz, &=macvar, &=debug) &macvar=&&&macvar;
%mend;

%macro test_foo;
  %local now;
  %let now=%sysfunc(datetime());

  %let result=;
  %formatSerialDateTime(dt=&now, tz="Asia/Tokyo", macvar=result, debug=1);
  %put &=result;
  
  %let result=;
  %formatSerialDateTime(dt=&now, tz='America/New_York', macvar=result, debug=1);
  %put &=result;

  %let result=;
  %formatSerialDateTime(dt=&now, tz='Europe/Istanbul', macvar=result, debug=1);
  %put &=result;

  %let result=;
  %formatSerialDateTime(dt=&now, tz='Asia/Kolkata', macvar=result, debug=1);
  %put &=result;

  %let result=;
  %formatSerialDateTime(dt=&now, tz='UTC', macvar=result, debug=1);
  %put &=result;
%mend;

options nomprint nosource nomlogic nosymbolgen;
%test_foo;




0 件のコメント :

コメントを投稿