[NEWSboard IBMi Forum]
Seite 1 von 2 1 2 Letzte
  1. #1
    Registriert seit
    Aug 2019
    Beiträge
    53

    Datum im ISO8601 Format

    Hallo Forum,

    Gibt es eine Funktion womit ich ein Datum in das ISO8601 Format konvertieren lässt. Ich habe dazu bisher leider noch nichts gefunden.

    Code:
    2020-06-12T09:50:01.001Z
    Vielen Dank!

  2. #2
    Registriert seit
    Feb 2001
    Beiträge
    20.207
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  3. #3
    Registriert seit
    Aug 2001
    Beiträge
    2.869
    TIMESTAMP_FORMAT wird an dieser Stelle wohl nicht viel helfen! Die Funktion wird verwendet um eine alphanumerische Darstellung eines Datums, einer Zeit oder einer Zeitmarke in eine echte Zeitmarke zu konvertieren.

    Für die Aufbereitung eines Datums- oder Zeitwertes ist die Funktion VARCHAR_FORMAT erforderlich:
    VARCHAR_FORMAT

    ... und dann sollte man immer darauf achten, dass man die Dokumentation der Db2 for i (und nicht Db2 LUW oder die einer anderen Datenbank) erwischt.

    Die Umsetzung in das gewünschte Format sollte wie folgt funktionieren.
    Code:
    Values(Replace(VarChar_Format(Current_Timestamp, 'YYYY-MM-DD HH24:MI:SS.FF3'), ' ', 'T') concat 'Z');
    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  4. #4
    Registriert seit
    Aug 2019
    Beiträge
    53
    Vielen Dank für die Hilfe. Wie müsste ich den dies im RPG aufrufen? Ich habe es wie folgt probiert aber leider ist die Variable nach dem Aufruf trotzdem leer.

    Code:
    EXEC SQL SET :ts = Values(Replace(VarChar_Format(      Current_Timestamp,
          'YYYY-MM-DD HH:MM:SS.FF3'), ' ', 'T') concat 'Z');

  5. #5
    Registriert seit
    Aug 2001
    Beiträge
    2.869
    Entweder
    Code:
    EXEC SQL SET :ts = Replace(VarChar_Format(Current_Timestamp,
          'YYYY-MM-DD HH24:MI:SS.FF3'), ' ', 'T') concat 'Z';
    Oder so:
    Code:
    EXEC SQL Values(Replace(VarChar_Format(Current_Timestamp,
          'YYYY-MM-DD HH24:MI:SS.FF3'), ' ', 'T') concat 'Z') into :ts;
    Birgitta
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  6. #6
    Registriert seit
    Oct 2019
    Beiträge
    16
    Birgittas Lösung verwendet das 12-Stunden Format und Monate anstatt Minuten.

    hier die korrigierte Variante:
    values replace(varchar_format(current_timestamp - current_timezone , 'YYYY-MM-DD HH24:MI:SS.FF3'), ' ', 'T') concat 'Z';

    Dabei ist zu beachten dass so nur die aktuelle Timestamp im ISO8601 Format ausgegeben werden kann. Wenn die Timestamp (leider ohne Zeitzone) zu einem früheren Zeitpunkt entstanden ist, ist es schwer nachzuvollziehen, unter welchem UTC Offset sie entstanden ist.

  7. #7
    Registriert seit
    Aug 2001
    Beiträge
    2.869
    Zitat Zitat von Ahoy Beitrag anzeigen
    Birgittas Lösung verwendet das 12-Stunden Format und Monate anstatt Minuten.
    Oups! Mal wieder nicht aufgepasst! Das merke ich dann meist (erst) beim Testen.
    Ich habe meine Beispiele korrigiert (allerdings ohne Berücksichtigung der Zeitzone)
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  8. #8
    Registriert seit
    Feb 2001
    Beiträge
    20.207
    Im ILERPG gehts mit %CHAR auch ohne SQL.

    %replace(%char(MyTimeStamp:*iso):' ':'T') + 'Z';
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  9. #9
    Registriert seit
    Aug 2001
    Beiträge
    2.869
    Zitat Zitat von Fuerchau Beitrag anzeigen
    Im ILERPG gehts mit %CHAR auch ohne SQL.

    %replace(%char(MyTimeStamp:*iso):' ':'T') + 'Z';
    Bist Du sicher, dass Du damit genau 3 Positionen nach dem letzten Punkt hast? M.E. hast Du 6!
    Birgitta Hauser

    Anwendungsmodernisierung, Beratung, Schulungen, Programmierung im Bereich RPG, SQL und Datenbank
    IBM Champion seit 2020 - 4. Jahr in Folge
    Birgitta Hauser - Modernization - Education - Consulting on IBM i

  10. #10
    Registriert seit
    Feb 2001
    Beiträge
    20.207
    Ja, das kannst du dann auch noch mit %subst() kürzen.
    Aber das weiß ja nun jeder;-).

    Ich wollte ja nur die Frage bzgl. ILERPG beantworten, dass du da kein SQL brauchst.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

  11. #11
    Registriert seit
    Oct 2019
    Beiträge
    16
    Hier noch eine Lösung die beliebige RPG Timestamps zu ISO8601 konvertieren kann.

    Code:
    **free
    
    ctl-opt dftactgrp(*no);
    ctl-opt option(*nodebugio: *srcstmt: *nounref);
    ctl-opt main(main);
    
    
    dcl-s time_t int(20) template;
    
    dcl-pr time like(time_t) extproc(*cwiden: 'time64');
      timeval  like(time_t) options(*omit);
    end-pr;
    
    dcl-ds struct_tm qualified template;
      tm_sec   int(10);  // seconds after the minute (0-61)
      tm_min   int(10);  // minutes after the hour (0-59)
      tm_hour  int(10);  // hours since midnight (0-23)
      tm_mday  int(10);  // day of the month (1-31)
      tm_mon   int(10);  // months since January (0-11)
      tm_year  int(10);  // years since 1900
      tm_wday  int(10);  // days since Sunday (0-6)
      tm_yday  int(10);  // days since January 1 (0-365)
      tm_isdst int(10);  // Daylight Saving Time flag
    end-ds;
    
    dcl-pr gmtime_r pointer extproc(*cwiden: 'gmtime64_r');
      timer  like(time_t) const;
      tm     like(struct_tm);
    end-pr;
    
    dcl-pr mktime like(time_t) extproc(*cwiden: 'mktime64');
      tm  like(struct_tm);
    end-pr;
    
    dcl-pr localtime_r pointer extproc(*cwiden: 'localtime64_r');
      timer  like(time_t) const;
      tm     like(struct_tm);
    end-pr;
    
    
    dcl-proc main;
      dsply time(*omit);
      dsply timestampToEpoch(%timestamp);
    
      dsply %timestamp(*sys: 0);
      dsply epochToTimestamp(timestampToEpoch(%timestamp));
    
      // 1 Stunde UTC-Offset für Winterzeit
      dsply timestampToISO8601(z'2021-01-01-14.00.00');
    
      // 2 Stunde UTC-Offset für Sommerzeit
      dsply timestampToISO8601(z'2021-08-01-14.00.00');
    
      // Timestamp innerhalb der überlappung von Sommer- und
      // Winterzeit wird als Winterzeit interpretiert
      dsply timestampToISO8601(z'2021-10-31-02.30.00');
    
      // Timestamp innerhalb der übersprungenen
      // Stunde wird als Winterzeit interpretiert
      dsply timestampToISO8601(z'2021-03-28-02.30.00');
    end-proc;
    
    
    // Konvertiert Unix Epoch Timestamp zu ISO8601 Timestamp
    dcl-proc epochToISO8601 export;
      dcl-pi *n char(20);
        timeval  like(time_t) const;
      end-pi;
      dcl-ds tm likeds(struct_tm) inz;
    
      // tm struct befüllen
      gmtime_r(timeval: tm);
    
      // ISO8601 Timestamp zusammensetzen
      return
        %subst(%editc(tm.tm_year + 1900: 'X'): 7: 4) + '-' +
        %subst(%editc(tm.tm_mon + 1: 'X'): 9: 2) + '-' +
        %subst(%editc(tm.tm_mday: 'X'): 9: 2) +  'T' +
        %subst(%editc(tm.tm_hour: 'X'): 9: 2) +  ':' +
        %subst(%editc(tm.tm_min: 'X'): 9: 2) +  ':' +
        %subst(%editc(tm.tm_sec: 'X'): 9: 2) + 'Z';
    end-proc;
    
    // Konvertiert RPG Timestamp zu ISO8601 Timestamp
    dcl-proc timestampToISO8601 export;
      dcl-pi *n char(20);
        timestamp timestamp(0) const;
        isdst     ind          const options(*nopass);
      end-pi;
      if %parms = 2;
        return epochToISO8601(timestampToEpoch(timestamp: isdst));
      else;
        return epochToISO8601(timestampToEpoch(timestamp));
      endif;
    end-proc;
    
    
    // konvertiert UNIX Epoch zu RPG Timestamp
    dcl-proc epochToTimestamp export;
      dcl-pi *n timestamp(0);
        time like(time_t) value;
      end-pi;
      dcl-ds tm likeds(struct_tm) inz;
    
      localtime_r(time: tm);
    
      return %timestamp(
        %subst(%editc(tm.tm_year + 1900: 'X'): 7: 4) +
        %subst(%editc(tm.tm_mon + 1: 'X'): 9: 2) +
        %subst(%editc(tm.tm_mday: 'X'): 9: 2) +
        %subst(%editc(tm.tm_hour: 'X'): 9: 2) +
        %subst(%editc(tm.tm_min: 'X'): 9: 2) +
        %subst(%editc(tm.tm_sec: 'X'): 9: 2):
        *iso0: 0
      );
    end-proc;
    
    
    // konvertiert RPG Timestamp zu UNIX Epoch
    dcl-proc timestampToEpoch export;
      dcl-pi *n like(time_t);
        timestamp timestamp(0) const;
        isdst     ind          const options(*nopass);
      end-pi;
      dcl-ds tm likeds(struct_tm) inz;
    
      tm.tm_year = %subdt(timestamp: *years) - 1900;
      tm.tm_mon  = %subdt(timestamp: *months) - 1;
      tm.tm_mday = %subdt(timestamp: *days);
      tm.tm_hour = %subdt(timestamp: *hours);
      tm.tm_min  = %subdt(timestamp: *minutes);
      tm.tm_sec  = %subdt(timestamp: *seconds);
    
      if %parms = 2;
        if isdst;
          tm.tm_isdst = 1;
        else;
          tm.tm_isdst = 0;
        endif;
      else;
        tm.tm_isdst = -1;
      endif;
    
      // convert to unix timestamp
      return mktime(tm);
    end-proc;

  12. #12
    Registriert seit
    Feb 2001
    Beiträge
    20.207
    Warum so kompliziert?
    Ein Timestamp wird in der Variablen als CHAR(22) im ISO-Format gespeichert.
    Dieses brauchst du dann nur per Redefine mit Zoned-Feldern zu deklarieren und kannst deinen Code um ganz viel kürzen:

    dcl-ds TSConv;
    dsTimestamp timestamp;
    dsYear zoned(2) pos(1);
    dsMonth zoned(2) pos(4);
    ....
    chYear char(2) pos(1);
    chMonth char(2) pos(4);
    ....
    end-ds;

    Damit kannst du den ganzen %subdt()-Kram abschaffen.
    Das Ganze gilt auch z.B. für ISO-Date und ISO-Time.
    Dienstleistungen? Die gibt es hier: http://www.fuerchau.de
    Das Excel-AddIn: https://www.ftsolutions.de/index.php/downloads
    BI? Da war doch noch was: http://www.ftsolutions.de

Similar Threads

  1. Format von PF ändern
    By _MG_ in forum NEWSboard Programmierung
    Antworten: 8
    Letzter Beitrag: 21-04-17, 14:09
  2. RDI - /End-Exec im festen Format
    By homue in forum NEWSboard Programmierung
    Antworten: 8
    Letzter Beitrag: 25-07-16, 15:27
  3. Feldgruppen im free-Format
    By kretzsch in forum NEWSboard Programmierung
    Antworten: 3
    Letzter Beitrag: 14-08-14, 13:02
  4. XML-Ausgabe in Cobol im Format UTF-8
    By Günter in forum NEWSboard Programmierung
    Antworten: 10
    Letzter Beitrag: 26-06-14, 15:10
  5. JDBC Datum Format EUR
    By camouflage in forum NEWSboard Java
    Antworten: 1
    Letzter Beitrag: 02-12-13, 16:58

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • You may not post attachments
  • You may not edit your posts
  •