Announcement

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

  • -convdate- (from SSC) behaviour

    Hi,

    regarding datetime manipulation, the -numdate- and -convdate-- commands, from SSC, are very handy.

    however, in the following situation, dates are converted to previous day.

    Code:
    clear
    input double dateref
    2.0196864e+12
    2.0223648e+12
    2.0248704e+12
    2.0275488e+12
    2.0301408e+12
    2.0328192e+12
    2.0354112e+12
    2.0380896e+12
     2.040768e+12
      2.04336e+12
    end
    format %tc dateref
    
    . convdate daily datevar_d = dateref
    
    . convdate monthly datevar_m = dateref
    
    . list
    
         +-------------------------------------------+
         |            dateref   datevar_d   dateva~m |
         |-------------------------------------------|
      1. | 01jan2024 00:00:00   31dec2023    2023m12 |
      2. | 01feb2024 00:00:00   01feb2024     2024m2 |
      3. | 01mar2024 00:00:00   29feb2024     2024m2 |
      4. | 01apr2024 00:00:00   01apr2024     2024m4 |
      5. | 01may2024 00:00:00   30apr2024     2024m4 |
         |-------------------------------------------|
      6. | 01jun2024 00:00:00   01jun2024     2024m6 |
      7. | 01jul2024 00:00:00   30jun2024     2024m6 |
      8. | 01aug2024 00:00:00   01aug2024     2024m8 |
      9. | 01sep2024 00:00:00   31aug2024     2024m8 |
     10. | 01oct2024 00:00:00   01oct2024    2024m10 |
         +-------------------------------------------+

    and seems obvious it is related to "00:00:00".

    Any clue?
    Last edited by Luis Pecht; 18 Nov 2024, 13:35.

  • #2
    Thanks for this. You found a bug. I wasn't carrying enough precision in initialising the new variable. Here is a temporary replacement for the code.

    Code:
    *! 1.2.2 NJC 18 November 2024
    *! 1.2.1 NJC 31 August 2017
    * 1.2.0 NJC 17 August 2017 
    * 1.1.0 NJC 3 August 2017 
    * 1.0.0 NJC 1 August 2017 
    program convdate2 
        version 12 
    
        /// get and check wanted date-time type, zapping any hyphens or percents 
        gettoken outtype 0 : 0 
        local outtype : subinstr local outtype "-" "", all 
        local outtype : subinstr local outtype "%" "", all 
    
        /// -- allowed are any Stata abbreviations     
        tokenize "tc tC td td tw tm tq th ty" 
    
        /// -- or (abbreviations of) any longer names 
        ///    date() predated daily() 
        local T clock Clock daily date weekly monthly quarterly ///
        halfyearly yearly 
    
        /// fine to coarse means order out > order in 
        /// coarse to fine means order in > order out 
        local order 1 1 2 2 3 4 5 6 7 
    
        local OK = 0 
    
        forval t = 1/9 { 
            if "`outtype'" == "``t''" { 
                local out "`: word `t' of `T''" 
                local nout = `: word `t' of `order'' 
                local OK 1 
                continue, break 
            }
        } 
    
        if `OK' == 0 { 
            local len = length("`outtype'") 
            tokenize "`T'" 
            forval t = 1/9 {  
                if "`outtype'" == substr("``t''", 1, `len') { 
                    local out "``t''" 
                    local nout = `: word `t' of `order'' 
                    local OK 1 
                    continue, break 
                }
            } 
        }
    
        if `OK' == 0 { 
            di as err "`outtype' unrecognised kind of date-time" 
            exit 498 
        } 
    
        // newvar = 
        gettoken newvar 0 : 0, parse("= ")  
        confirm new var `newvar' 
        gettoken eqs 0 : 0, parse("= ") 
        if "`eqs'" != "=" { 
            di as err "invalid syntax" 
            exit 198
        } 
    
        /// rest of syntax
        syntax varname(numeric) [if] [in] , ///
        [last Format(str) Dryrun varlabel(str)] 
    
        marksample touse 
        quietly count if `touse' 
        if r(N) == 0 error 2000 
        
        /// if format requested check consistency with date type 
        /// else default format assigned 
        local t = substr("`out'", 1, 1)  
        if "`format'" != "" { 
            /// treat "%-" as if "%" 
            local Format : subinstr local format "%-" "%" 
            if substr("`Format'", 3, 1) != "`t'" { 
                di as err "`format' format does not match `out'" 
                exit 498 
            }
        } 
        else local format %t`t'
        
        /// check that varlist has a date format 
        local informat : format `varlist' 
        local informat : subinstr local informat "%-" "%", all 
        
        local intype = substr("`informat'", 2, 1) 
        if "`intype'" != "t" { 
            di as err "`informat' format does not make date type explicit" 
            exit 498 
        }
    
        tokenize "c C d d w m q h y" 
        forval t = 1/9 { 
            if substr("`informat'", 3, 1) == "``t''" { 
                local nin = `: word `t' of `order'' 
                continue, break 
            }
        }
        if "`nin'" == "" { 
            di as err "puzzling existing format `informat'?" 
            exit 498 
        }
    
        if `nout' > `nin' & "`last'" != "" { 
            di as err "{p}warning: " /// 
                      "last option irrelevant as converting fine to coarse{p_end}" 
            /// blank it out 
            local last     
        } 
                
        local intype = substr("`informat'", 3, 1)
        local oldvar "`varlist'" 
        local last = "`last'" != "" 
    
        /// dry run or for real     
        if "`dryrun'" != "" { 
            Tryit `touse' `newvar' `oldvar' `intype' `out' `format' `last' 
        } 
        else { 
            Doit `touse' `newvar' `oldvar' `intype' `out' `format' `last' 
            
            if "`varlabel'" == "" { 
                local varlabel : variable label `oldvar' 
                if `"`varlabel'"' == "" local varlabel `oldvar' 
    
                if `last' local text "last "            
                label var `newvar' `"`text'`out' date from `varlabel'"' 
            } 
            else label var `newvar' `"`varlabel'"'
        }     
    end 
    
    program Tryit 
        args touse newvar oldvar intype out format last 
        tempvar work toshow nmiss 
    
        if inlist("`out'", "clock", "Clock", "c", "C") | inlist("`intype'", "clock", "Clock", "c", "C") { 
            local vtype "double" 
        } 
        local out = substr("`out'", 1, 1) 
        quietly { 
            gen `vtype' `work' = cond(`last', `oldvar' + 1, `oldvar')  
            replace `work' = `out'ofd(dof`intype'(`work')) if `touse' 
            if `last' replace `work' = `work' - 1 
    
            gen `toshow' = sum(`touse' & (`work' < .)) 
            gen `nmiss' = sum(`touse' & (`work' == .))  
        }
    
        format `work' `format' 
        local len = max(length("`: char `oldvar'[varname]'"), length("`newvar'")) 
        char `work'[varname] "`newvar'" 
    
        list `oldvar' `work' if `touse' & `toshow' <= 5 & `nmiss' <= 20, ///
        subvarname abbrev(`len')
    
        di _n as txt "{p}note: " ///   
        "`newvar' is not yet a variable in your dataset{p_end}"  
    
        if `toshow'[_N] == 0 { 
            di _n as txt "{p}all values would be missing: " ///
            "check {stata help datetime}{p_end}" 
        } 
    end 
    
    program Doit 
        args touse newvar oldvar intype out format last 
        
        if inlist("`out'", "clock", "Clock", "c", "C") | inlist("`intype'", "clock", "Clock", "c", "C") { 
            local vtype "double" 
        } 
        local out = substr("`out'", 1, 1) 
    
        quietly { 
            gen `vtype' `newvar' = cond(`last', `oldvar' + 1, `oldvar') if `touse' 
            replace `newvar' = `out'ofd(dof`intype'(`newvar')) if `touse'  
            if `last' replace `newvar' = `newvar' - 1 
    
            if "`out'" == "" compress `newvar' 
        } 
    
        format `newvar' `format' 
    end

    Comment


    • #3
      As reported in https://www.statalist.org/forums/for...ariables/page2 the convdate files have been updated on SSC.

      Thanks again to Luis Pecht for reporting the bug.

      Comment


      • #4
        Thanks Nick.

        Comment

        Working...
        X