Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Apply local function from ado on data

    I possess a dataset with dates in the Jalali calendar format. I have developed an ado file to convert the date format from Jalali to Gregorian, as demonstrated below:

    Code:
    . j2g 14011209
    20230228
    
    . g2j 20230228
    14011209
    Now, my objective is to add a new column in the dataset that displays the corresponding Gregorian date for each entry. But I got error:

    Code:
    . gen requestDate_Grg = j2g(requestDate)
    unknown function j2g()

  • #2
    Evidently you wrote two commands that take individual values and map them from one calendar to another. But that doesn't make the commands into functions, and in fact users can't add functions to Stata that work as you wrote them.

    To give better advice we need to see the code of your commands, or at least one of them.

    Comment


    • #3
      Please see the following code:

      Code:
      program g2j, rclass
          version 1.1
          args gdate
          local gy = int(`gdate' / 10000)
          local gm = mod(int(`gdate' / 100), 100)
          local gd = mod(`gdate', 100)
          local g_d_m 0 31 59 90 120 151 181 212 243 273 304 334
          if (`gm' > 2) {
              local gy2 = `gy' + 1
          } 
          else {
              local gy2 = `gy'
          }
          local gmm = `gm'
          local tmp : word `gmm' of `g_d_m'
          local days = 355666 + (365 * `gy') + int((`gy2' + 3) / 4) - int((`gy2' + 99) / 100) + int((`gy2' + 399) / 400) + `gd' + `tmp'
          local jy = -1595 + (33 * int(`days' / 12053))
          local days = mod(`days', 12053)
          local jy = `jy' + 4 * int(`days' / 1461)
          local days = mod(`days', 1461)
          if (`days' > 365) {
              local jy = `jy' + int((`days' - 1) / 365)
              local days = mod(`days' - 1, 365)
          }
          if (`days' < 186) {
              local jm = 1 + int(`days' / 31)
              local jd = 1 + mod(`days', 31)
          }
          else {
              local jm = 7 + int((`days' - 186) / 30)
              local jd = 1 + mod(`days' - 186, 30)
          }
          if (`jd' < 10) {
              if (`jm' < 10) {
                  dis `jy' "0" `jm' "0" `jd'
              }
              else {
                  dis `jy' "" `jm' "0" `jd'
              }
          }
          else {
              if (`jm' < 10) {
                  dis `jy' "0" `jm' "" `jd'
              }
              else {
                  dis `jy' "" `jm' "" `jd'
              }
          }
          return local jy `jy' jm `jm' jd `jd' 
      end

      Comment


      • #4
        There is a crude and unsatisfactory way to convert this to a command, which I took. That is to write a wrapper for your code and call it up repeatedly for each value of a variable. Even that presented some puzzles and I made some changes where the code seemed odd. (The return local line I don't understand.)

        The better way to convert this to a command is to write it in terms of variables, which I didn't do.

        Code:
        program gregorian_to_jalali 
            syntax varname(numeric) [if] [in] , Generate(str)
            local gdate `varlist'
            
            marksample touse 
            quietly count if `touse'
            if r(N) == 0 error 2000 
            
            quietly generate long `generate' = . 
            
            local N = _N 
            
            quietly forval i = 1/`N' { 
                if `touse'[`i'] {
                    local this = `gdate'[`i']
                    g2j `this'
                    replace `generate' = `jdate' in `i'
                }
            }
        end 
        
        program g2j, rclass
            version 1.1
            args gdate
            local gy = int(`gdate' / 10000)
            local gm = mod(int(`gdate' / 100), 100)
            local gd = mod(`gdate', 100)
            local g_d_m 0 31 59 90 120 151 181 212 243 273 304 334
            if (`gm' > 2) {
                local gy2 = `gy' + 1
            } 
            else {
                local gy2 = `gy'
            }
            local gmm = `gm'
            local tmp : word `gmm' of `g_d_m'
            local days = 355666 + (365 * `gy') + int((`gy2' + 3) / 4) - int((`gy2' + 99) / 100) + int((`gy2' + 399) / 400) + `gd' + `tmp'
            local jy = -1595 + (33 * int(`days' / 12053))
            local days = mod(`days', 12053)
            local jy = `jy' + 4 * int(`days' / 1461)
            local days = mod(`days', 1461)
            if (`days' > 365) {
                local jy = `jy' + int((`days' - 1) / 365)
                local days = mod(`days' - 1, 365)
            }
            if (`days' < 186) {
                local jm = 1 + int(`days' / 31)
                local jd = 1 + mod(`days', 31)
            }
            else {
                local jm = 7 + int((`days' - 186) / 30)
                local jd = 1 + mod(`days' - 186, 30)
            }
            
            local jdate = "`jy'" + strofreal(`jm', "%02.0f") + strofreal(`jd', "%02.0f")
            c_local jdate "`jdate'" 
        end
        Token test script:

        Code:
        clear
        set obs 2 
        gen long gr = 20230228 in 1 
        replace gr = 20230301 in 2 
        format gr %10.0f 
        
        gregorian_to_jalali gr, gen(ja)

        Comment


        • #5
          Thank you, although I want to know the mature and satisfactory way to do it.

          Regards

          Comment


          • #6
            Good, and so my advice is to read the chapters on programming in [U]. That can't be taught in a short post or a few minutes, as you will appreciate. Where did the code in #3 come from?

            Comment


            • #7
              I have created the Stata code myself, which converts Jalali dates to Gregorian dates and vice versa using an algorithm. While developing the code, I referred to different functions in Stata. If you believe that this code can be useful for others, please advise me on the best way to publish it. Would it be suitable to submit it to Stata Journal, for instance?

              Comment


              • #8
                I would see something like this as best suited for a site like SSC. I am not speaking as an Editor of the Stata Journal, as we comment only privately in response to queries or submissions.

                Comment

                Working...
                X