SAP R/3 форум ABAP консультантов
Russian ABAP Developer's Club

Home - FAQ - Search - Memberlist - Usergroups - Profile - Log in to check your private messages - Register - Log in - English
Blogs - Weblogs News

Convert ISO 8601 Time to ABAP Representation



 
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Programming Techniques | Приемы программирования -> Conversion
View previous topic :: View next topic  
Author Message
admin
Администратор
Администратор



Joined: 01 Sep 2007
Posts: 1639

PostPosted: Mon Feb 25, 2008 1:01 pm    Post subject: Convert ISO 8601 Time to ABAP Representation Reply with quote

Code:
report zcen_iso8601 no standard page heading.title
**************************************************
* T R A N S L A T I O N   F O R M
*
* F O R   I S O   8 6 0 1   T I M E   S T A M P S
*
*   Version 1.00
*   This code allows direct translation of date/time string formatted
*   in the notation defined by ISO 8601 into abap date/time format.
*
*   It does also almost fully support RFC 3339.
*
*   Not supported ISO 8601 formats are:
*     - Intervals
*     - Periods
*     - Some formats with assumed data
*     - Fractional parts of seconds
*
*   Not supported RFC 3339 formats are:
*     - Fractional parts of seconds
*
*   This is freeware. Please read the terms of use.
*   Written by Urs Rohner, Rohner IT Consulting & Engineering
*
*   Contact Author: Urs Rohner
*
*
*
*
*
*references
* [1] W3C Date and Time Formats
*     http://www.w3.org/TR/NOTE-datetime
* [2] Summary on International Standard Date and Time Notations
*     http://www.cl.cam.ac.uk/~mgk25/iso-time.html
*
*
*comments
*
* Recognized Date Formats:
*   Format     Pattern    Granularity  Remark
*   ---------- ---------- -----------  -------------------
*   yy         ++         Y            century assumed
*   cccc       ++++       Y
*   -kkk       -+++       D            year assumed
*   yykkk      +++++      D            century assumed
*   yy-mm      ++-++      M            century assumed
*   yyWww      ++W++      W            century assumed
*   yymmdd     ++++++     D            century assumed
*   yy-kkk     ++-+++     D            century assumed
*   yy-Www     ++-W++     W            century assumed
*   yyWwwo     ++W+++     D            century assumed
*   cccckkk    +++++++    D
*   cccc-mm    ++++-++    M
*   ccccWww    ++++W++    W
*   ccccmmdd   ++++++++   D
*   cccc-kkk   ++++-+++   D
*   ccccWwwo   ++++W+++   D
*   cccc-Www   ++++-W++   W
*   yy-Www-o   ++-W++-+   D            century assumed
*   yy-mm-dd   ++-++-++   D            century assumed
*   cccc-Www-o ++++-W++-+ D
*   cccc-mm-dd ++++-++-++ D
* Literals are: '-', 'W'
*
* Recognized Time Formats:
*   Format     Pattern    Granularity  Remark
*   ---------- ---------- -----------  -------------------
*   hh         ++         h
*   hhii       ++++       m
*   hhiiss     ++++++     s
*   hh:ii      ++:++      m
*   hh:ii:ss   ++:++:++   s
* Literals are: ':'
*
* Recognized Timezone Formats:
*   Format     Pattern    Sign        Remark
*   ---------- ---------- ----------  -------------------
*   Z          Z          0           UTC
*   +tt        #+++       +1
*   +ttff      #+++++     +1
*   +tt:ff     #+++:++    +1
*   -tt        -++        -1
*   -ttff      -++++      -1
*   -tt:ff     -++:++     -1
* Literals are: 'Z', '-', '#+', ':'
*
* Granularity, ie. degree of Resolution:
*   res_  Degree      Remark                                   Res
*   ----  ----------  ---------------------------------------  -------
*   'Y'   Year        only year given                          lowest
*   'M'   Year Month  year plus month given                    month
*   'W'   Year Week   year plus week number given              week
*   'D'   Year Day    exact date given, ie. year month day     day
*   'h'   Hour        date plus hour                           hour
*   'm'   Minute      date plus hour and minute                minute
*   's'   Second      date and exact time                      highest
*
*
**********************************************************

  types:
    " Granularity of probed string
    t_granularity(7) type c.

  types:
    " maximal datr/time representation in ISO 8601
    " without fractional part
    t_raw(25)        type c.
  types:
    " Intermediate data container
    begin of t_vars,
      granularity    type t_granularity,  " pattern granularity
      " date related
      c(4)           type n, _c type c,   " 4 digit year
      y(2)           type n, _y type c,   " 2 digit year
      k(3)           type n, _k type c,   " day in year
      w(2)           type n, _w type c,   " week in year
      m(2)           type n, _m type c,   " month
      d(2)           type n, _d type c,   " day
      o(1)           type n, _o type c,   " day in week
      " time related
      h(2)           type n, _h type c,   " hour
      i(2)           type n, _i type c,   " minute
      s(2)           type n, _s type c,   " second
      " timezone related
      sign           type i,              " sign to zone difference
      t(2)           type n, _t type c,   " difference in hours
      f(2)           type n, _f type c,   " difference in minutes
    end of t_vars.



* Method: m_iso2time_patt>
* Convert a iso2time search pattern to an Abap string pattern
  define m_iso2time_patt>.
    perform m_iso2time_patt using &1 &2 &3.
  end-of-definition.

  form m_iso2time_patt using
    value(ipat_)     type t_raw           " internal iso2time pattern
    apat_            type t_raw           " Abap string pattern
    res_             type t_granularity.  " derived resolution code

    data:
      _vars(13)      type c,
      _l             type i,
      _x             type i,
      _y             type i.

    " compute granularity of given pattern
    define m_iso2time_patt_res>.
      if &1 ca &2.
        concatenate res_ &3 into res_.
      endif.
      concatenate _vars &2 into _vars.
    end-of-definition.

    " initialize
    clear:
      apat_,
      res_.

    " compute patterns granularity and variable identifiers
    m_iso2time_patt_res> ipat_:
      'cy' 'Y', 'm'  'M', 'w'  'W',
      'k'  'D', 'o'  'D', 'd'  'D',
      'h'  'h', 'i'  'm', 's'  's',
      't'  ' ', 'f'  ' '.
    if not res_ is initial.
      " create a pattern
      _l = strlen( ipat_ ).
      do _l times.
        if ipat_+_y(1) ca _vars.
          apat_+_x(1) = '+'.
          add 1 to _x.
        elseif ipat_+_y(1) eq '+'.
          apat_+_x(2) = '#+'.
          add 2 to _x.
        else.
          apat_+_x(1) = ipat_+_y(1).
          add 1 to _x.
        endif.
        add 1 to _y.
      enddo.
    endif.
  endform.


* Method: m_iso2time_setvar>
* Prefill Numc Variables
  define m_iso2time_setvar>.
    perform m_iso2time_setvar using &1 &2 &3.
  end-of-definition.

  form m_iso2time_setvar using
    value(raw_)     type t_raw   " raw date string to test
    vars_           type t_vars  " variable container
    value(pattern_) type t_raw.  " pattern to check

    data:
      _pattern      type t_raw,
      _l            type i,
      _x            type i,
      _c            type c,
      _last_c       type c,
      _digit        type i,
      _n(10)        type c.

    field-symbols:
      <n>.

    if vars_ is initial and not raw_ is initial.
      " create pattern
      m_iso2time_patt> pattern_ _pattern vars_-granularity.
      _l = strlen( raw_ ).
      if raw_+0(_l) cp _pattern.
        " pattern matches, try to fill variables
        " loop thru all characters of raw string
        do _l times.
          " capitalize character in pattern
          _c = pattern_+_x(1).
          translate _c to upper case.
          " now check what the current character represents
          if _c eq pattern_+_x(1).
            " it's a literal
            if pattern_ ca 't'.
              " time with UTC offset
              case _c.
                when '+'. vars_-sign = 1.
                when '-'. vars_-sign = -1.
              endcase.
            elseif _c eq 'Z'.
              vars_-sign = 1. " time in UTC
            endif.
          else.
            " it's part of a variable
            if raw_+_x(1) co '0123456789'.
              " as expected its a digit
              if _c ne _last_c.
                clear _digit.
              endif.
              " set digit
              concatenate 'VARS_-' _c into _n.
              assign (_n) to <n>.
              <n>+_digit(1) = raw_+_x(1).
              " set set flag
              concatenate 'VARS_-_' _c into _n.
              assign (_n) to <n>.
              <n> = 'X'.
              add 1 to _digit.
              _last_c = _c.
            else.
              " error, digit expected
              clear vars_.
              exit.
            endif.
          endif.
          add 1 to _x.
        enddo.
      else.
        " does not match pattern
        clear vars_.
      endif.
    endif.
  endform.


* Method: m_iso2time_date_setvar>
* Prefill Numc Variables
  define m_iso2time_date_setvar>.
    perform m_iso2time_date_setvar using &1 &2 &3.
  end-of-definition.

  form m_iso2time_date_setvar using
    value(raw_)     type t_raw   " raw date string to test
    vars_           type t_vars  " variable container
    date_           type d.      " date

    data:
      _week         type scal-week.

    clear:
      vars_,
      date_.

    m_iso2time_setvar> raw_ vars_:
      'yy',      'cccc',     'yy-kkk',   'cccc-kkk',
      'yy-mm',   'cccc-mm',  'yyWwwo',   'ccccWwwo',
      'yyWww',   'ccccWww',  'yy-Www-o', 'cccc-Www-o',
      'yy-Www',  'cccc-Www', 'yymmdd',   'ccccmmdd',
      'yykkk',   'cccckkk',  'yy-mm-dd', 'cccc-mm-dd',
      '-kkk'.
    if not vars_ is initial.
      " everything okay so far, try to compile date

      " Do Year
      if not vars_-_c is initial.
        " set year
        date_+0(4) = vars_-c.
      elseif not vars_-_y is initial.
        " set year, assume century
        date_+2(2) = vars_-y.
        if vars_-y gt '21'.   " I chose year 2021, SAP has currently
          date_+0(2) = '19'.  " some problems going beyond that date
        else.
          date_+0(2) = '20'.
        endif.
      else.
        " not given, set to current year
        date_+0(4) = sy-datum+0(4).
      endif.

      " Do Month
      if not vars_-_m is initial.
        if vars_-m between 1 and 12.
          date_+4(2) = vars_-m.
        else.
          clear vars_. " month out of range
        endif.
      endif.

      " Do Day
      if not vars_-_d is initial.
        if vars_-d between 1 and 31.
          date_+6(2) = vars_-d.
        else.
          clear vars_. " day out of range
        endif.
      endif.

      " Do day of year
      if not vars_-_k is initial.
        if vars_-k between 1 and 365.
          date_+4(4) = '0101'.
          date_ = date_ + vars_-k - 1.
        else.
          clear vars_. " day of year out of range
        endif.
      endif.

      if not vars_-_w is initial.
        " compute date out of week number
        if vars_-w between 1 and 53.
          _week+0(4) = date_+0(4).
          _week+4(2) = vars_-w.
          call function 'WEEK_GET_FIRST_DAY'
            exporting
              week         = _week
            importing
              date         = date_
            exceptions
             week_invalid = 1
             others       = 2.
          if not sy-subrc is initial.
            clear vars_. " invalid week specified
          endif.
        else.
          clear vars_. " week number out of range
        endif.
      endif.

      " add day number to date
      if not vars_-_o is initial.
        if vars_-o between 1 and 7.
          date_ = date_ + vars_-o - 1.
        else.
          clear vars_. " weekday number out of range
        endif.
      endif.

      if vars_-granularity ca 'D'.
        " almost have it
        call function 'DATE_CHECK_PLAUSIBILITY'
          exporting
            date                      = date_
          exceptions
            plausibility_check_failed = 1
            others                    = 2.
        if not sy-subrc is initial.
          clear vars_. " something else wrong with date
        endif.
      endif.

    endif.

    if vars_ is initial.
      clear date_.
    endif.
  endform.


* Method: m_iso2time_time_setvar>
* Prefill Numc Variables
  define m_iso2time_time_setvar>.
    perform m_iso2time_time_setvar using &1 &2 &3 &4 &5 &6.
  end-of-definition.

  form m_iso2time_time_setvar using
    value(raw_)     type t_raw   " raw time string to test
    vars_           type t_vars  " variable container
    time_           type t       " time
    zone_           type i       " timezone difference
    zone_unknown_   type c       " timezone specified as unknown
    offset_         type i.      " date offset

    data:
      _time         type i.

    clear:
      vars_,
      time_,
      zone_,
      zone_unknown_,
      offset_.

    m_iso2time_setvar>  raw_ vars_:
      'hhZ',            'hhiiZ',           'hhiissZ',
      'hh:iiZ',         'hh:ii:ssZ',       'hh+tt',
      'hhii+tt',        'hhiiss+tt',       'hh:ii+tt',
      'hh:ii:ss+tt',    'hh+ttff',         'hhii+ttff',
      'hhiiss+ttff',    'hh:ii+ttff',      'hh:ii:ss+ttff',
      'hh+tt:ff',       'hhii+tt:ff',      'hhiiss+tt:ff',
      'hh:ii+tt:ff',    'hh:ii:ss+tt:ff',  'hh-tt',
      'hhii-tt',        'hhiiss-tt',       'hh:ii-tt',
      'hh:ii:ss-tt',    'hh-ttff ',        'hhii-ttff',
      'hhiiss-ttff',    'hh:ii-ttff',      'hh:ii:ss-ttff',
      'hh-tt:ff',       'hhii-tt:ff',      'hhiiss-tt:ff',
      'hh:ii-tt:ff',    'hh:ii:ss-tt:ff'.
    if not vars_ is initial.

      " compute timezone difference
      if not vars_-_t is initial.
        if vars_-t between 0 and 12.
          zone_ = vars_-t * 60.
        else.
          clear vars_. " timezone hours out of range
        endif.
      endif.
      if not vars_-_f is initial.
        if vars_-f between 0 and 59.
          add vars_-f to zone_.
        else.
          clear vars_. " timezone minutes out of range
        endif.
      endif.
      multiply zone_ by vars_-sign.
      if not zone_  between -720 and 720.
        clear vars_. " timezone makes no sense
      endif.
      " special case in RFC3339
      " check whether timezone is unknown
      if vars_-sign eq -1
      and not vars_-_t is initial and vars_-t eq 0
      and not vars_-_f is initial and vars_-f eq 0.
        zone_unknown_ = 'X'.
      endif.

      " set time
      " first, treat special case midnight
      if vars_-granularity ca 's'.
        if vars_-h eq 24 and vars_-m eq 0 and vars_-s eq 0.
          clear vars_-h.
          offset_ = 1.
        endif.
      endif.

      " do hours
      if not vars_-_h is initial.
        if vars_-h between 0 and 23.
          time_+0(2) = vars_-h.
        else.
          clear vars_. " wrong hour
        endif.
      endif.

      " do minutes
      if not vars_-_i is initial.
        if vars_-i between 0 and 59.
          time_+2(2) = vars_-i.
        else.
          clear vars_. " wrong minutes
        endif.
      endif.

      " do seconds
      if not vars_-_s is initial.
        if vars_-s between 0 and 59.
          time_+4(2) = vars_-s.
        elseif vars_-s eq 60.
          " check whether we have a leap second
          _time = vars_-i + vars_-h * 60 + zone_ * -1 + 1.
          if _time eq 1440. " minutes per day
            " hmm, what should we do with it?
            " as far as i know, sap's Abap VM does not support
            " leap seconds
            time_+4(2) = vars_-s.
          else.
            clear vars_. " wrong second
          endif.
        else.
          clear vars_. " seconds out of range
        endif.
      endif.

    endif.

    if vars_ is initial.
      clear:
        time_,
        zone_,
        zone_unknown_,
        offset_.
    endif.
  endform.


* Method: m_iso2time>
* Convert some ISO 8601 Time strings to ABAP representation
  define m_iso2time>.
    perform m_iso2time using &1 &2 &3 &4 &5 &6 &7.
  end-of-definition.

  form m_iso2time using               " Parameters:
    value(iso_)    type any           " - ISO 8601 date/time string
    granularity_   type t_granularity " - degree of resolution
    date_          type d             " - date
    time_          type t             " - time
    zone_          type i             " - timezone difference in minutes
    zone_unknown_  type c             " - timezone specified as unknown
    rc_            type sy-subrc.     " - return code

    data:
      _l           type i,
      _exclusive   type c,
      _offset      type i,
      _raw         type t_raw,
      _rawdate     type t_raw,
      _rawtime     type t_raw,
      _date_vars   type t_vars,
      _time_vars   type t_vars.

    clear:
      granularity_,
      date_,
      time_,
      zone_,
      rc_.

    " check input parameter
    if not iso_ is initial.
      " check length
      _raw = iso_.
      if _raw eq iso_.
        " adjust it
        shift _raw left deleting leading space.
        _l = strlen( _raw ).
        translate _raw+0(_l):
          to upper case,  " switch to Capitals
          using ',.',     " change decimal commas to points
          using ' T'.     " date/time delimiter might be a space
        " try to find out what string contains
        if _raw ca 'T'.
          " it contains both time and date
          split _raw at 'T' into _rawdate _rawtime.
        else.
          " it contains either a date or a time
          _rawdate = _rawtime = _raw.
          _exclusive = 'X'.
        endif.
        " check date format
        m_iso2time_date_setvar>
          _rawdate _date_vars date_.
        " check date format
        m_iso2time_time_setvar>
          _rawtime _time_vars time_ zone_ zone_unknown_ _offset.
        case _exclusive.
          when ' '. " time and date specified
            if _date_vars is initial or _time_vars is initial.
              rc_ = 2. " syntax error
            endif.
          when 'X'. " either time or date specified
            if _date_vars is initial and _time_vars is initial.
              rc_ = 3. " syntax error
            elseif not _date_vars is initial
              and  not _time_vars is initial.
              rc_ = 4. " ambigous, could be date or time
            endif.
        endcase.
        if rc_ is initial.
          concatenate _date_vars-granularity _time_vars-granularity
            into granularity_.
          if not _date_vars is initial and not _time_vars is initial.
            add _offset to date_.
          endif.
        else.
          clear:
            date_,
            time_,
            zone_.
        endif.
      endif.
    else.
      rc_ = 1. " no string given
    endif.
  endform.


*
* S E L E C T I O N    S C R E E N
*
  parameters:
    iso_(40) type c.

*
* G L O B A L S
*
   data:
     rc_     type sy-subrc,
     date_   type d,
     time_   type t,
     zone_   type i,
     unkn_   type c,
     res_    type t_granularity.

*
* P B O ( )
*
  initialization.
    concatenate
      sy-datum+0(4) '-'
      sy-datum+4(2) '-'
      sy-datum+6(2) 'T'
      sy-uzeit+0(2) ':'
      sy-uzeit+2(2) ':'
      sy-uzeit+4(2) '+'
      '01'          ':'
      '00'
    into iso_.
*
* P A I ( )
*
  start-of-selection.

    m_iso2time> iso_ res_ date_ time_ zone_ unkn_ rc_.
    write:
      / 'ISO String ', iso_,
      / 'Granularity', res_,
      / 'Date       ', date_     dd/mm/yyyy,
      / 'Time       ', (8) time_ using edit mask '__:__:__',
      / 'Zone       ', zone_,
      / ' Unknown   ', unkn_,
      / 'Return Code', rc_.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Programming Techniques | Приемы программирования -> Conversion All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG.
SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG.
Every effort is made to ensure content integrity. Use information on this site at your own risk.