go to post Vitaliy Serdtsev · Jun 22, 2018 Use %UTC instead of %TimeStamp In this case, all conversions will be performed automatically. Simple example: Class dc.test Extends %Persistent [ Final ] { Property CreationTime As %TimeStamp [ InitialExpression = {$ZDateTime($ZTimeStamp, 3, 1, 2)} ]; Property utc As %UTC [ InitialExpression = {##class(%UTC).NowUTC()} ]; /// d ##class(dc.test).Test() ClassMethod Test() { d ..%KillExtent() &sql(insert into dc.test default values) zw ^dc.testD w ! ; %SelectMode = DISPLAY d ##class(%SQL.Statement).%ExecDirect(##class(%SQL.Statement).%New(2),"select * from dc.test").%Display($c(9,9)) w ! ; %SelectMode = ODBC d ##class(%SQL.Statement).%ExecDirect(##class(%SQL.Statement).%New(1),"select * from dc.test").%Display($c(9,9)) w ! ; %SelectMode = LOGICAL d ##class(%SQL.Statement).%ExecDirect(##class(%SQL.Statement).%New(0),"select * from dc.test").%Display($c(9,9)) } }Result: USER>d ##class(dc.test).Test() ^dc.testD=1 ^dc.testD(1)=$lb("2018-06-22 14:58:11.61","2018-06-22 14:58:11.618") note that the database stores the same values ID CreationTime utc 1 2018-06-22 14:58:11.61 2018-06-22 17:58:11.618 1 Rows(s) Affected ID CreationTime utc 1 2018-06-22 14:58:11.61 2018-06-22 17:58:11.618 1 Rows(s) Affected ID CreationTime utc 1 2018-06-22 14:58:11.61 2018-06-22 14:58:11.618 1 Rows(s) AffectedSimilarly, you can play with the query in the Portal or any ODBC/JDBC client. PS: don't forget about SQL Functions: %internal()/%external(), %odbcin()/%odbcout().
go to post Vitaliy Serdtsev · Jun 22, 2018 Useful links: SQL and NLS Collations Collations in Caché This issue dares relatively simply: Create the required collation tables. Fortunately, for some languages, they are already included and can be taken as a basis. In complex cases, you can contact to WRC. Check their list and status: USER>zn "%SYS" %SYS>d ^COLLATE Status Number Abbrev Name ---------- ------ ------ ---------------------- Built-in 0 OANS ISM Pre-6.2 Built-in 1 ANSI ISM 6.2->6.4 Built-in 2 COBR Ipsum/Cobra Built-in 3 DTMC DTM-compatible Built-in 4 CBR2 Ipsum/Cobra-2 Built-in 5 UNIC Cache standard Not loaded 10 GER1 German1 Not loaded 11 POR1 Portuguese1 Not loaded 12 POL1 Polish1 Not loaded 13 GER2 German2 Not loaded 14 SPA1 Spanish1 Not loaded 15 DAN1 Danish1 Available 16 CYR1 Cyrillic1 Not loaded 17 GRE1 Greek1 Not loaded 18 CZE1 Czech1 Not loaded 19 CZE2 Czech2 Not loaded 20 POR2 Portuguese2 Not loaded 21 FIN1 Finnish1 Not loaded 22 JAP1 Japanese1 Not loaded 24 POL2 Polish2 Not loaded 27 FRE1 French1 Not loaded 28 FIN2 Finnish2 Available 29 HUN1 Hungarian1 Available 30 GER3 German3 Not loaded 31 POL3 Polish3 Not loaded 32 SPA2 Spanish2 Not loaded 33 DAN2 Danish2 Not loaded 34 GRE2 Greek2 Not loaded 35 FIN3 Finnish3 Not loaded 36 LIT1 Lithuanian1 Available 37 CYR3 Cyrillic3 Not loaded 38 SLO1 Slovenian1 Not loaded 39 SLO2 Slovenian2 Not loaded 40 TUR1 Turkish1 Not loaded 41 DAN3 Danish3 Available 42 UKR1 Ukrainian1 Available 43 CYR4 Cyrillic4 Not loaded 44 CZE3 Czech3 Not loaded 46 MAL1 Maltese1 Not loaded 48 MAL2 Maltese2 Not loaded 49 SPA4 Spanish4 Not loaded 50 SLO1 Slovak1 Not loaded 51 SPA5 Spanish5 Not loaded 52 FIN4 Finnish4 Not loaded 53 CZE4 Czech4 Built-in 128 OSTR ISM Pre-6.2 string Built-in 129 NSTR ISM 6.2->6.4 string Built-in 133 USTR Cache standard string Available 144 CYR1S Cyrillic1 string Available 157 HUN1S Hungarian1 string Available 158 GER3S German3 string Available 165 CYR3S Cyrillic3 string Available 170 UKR1S Ukrainian1 string Available 171 CYR4S Cyrillic4 string load the new collation tables to your current locale for Storage make mapping your indexes in separate globals with own collation Profit! Here are two small examples: Class dc.test1 Extends %Persistent { Index iDE On DescDE As EXACT; Index iHU On DescHU As EXACT; Index iRU On DescRU As EXACT; Property DescDE As %String; Property DescHU As %String; Property DescRU As %String; ClassMethod LoadColTables() [ Private ] { s r=$$$NO try { $$$AddAllRoleTemporaryInTry n $namespace s $namespace="%SYS" $$$ThrowOnError(##class(Config.NLS.Tables).Load("deuw","COL","German3")) $$$ThrowOnError(##class(Config.NLS.Tables).Load("hunw","COL","Hungarian1")) $$$ThrowOnError(##class(Config.NLS.Tables).Load("rusw","COL","Cyrillic4")) ;d ^COLLATE ; for check only s r=$$$YES }catch(ex) { w ex.DisplayString(),! } q r } /// d ##class(dc.test1).Test() ClassMethod Test() { q:'..LoadColTables() d ..%KillExtent() &sql(insert into dc.test1(DescDE,DescHU,DescRU) select 'Straßer','csak','Прохор' union all select 'Straster','comb','Павел' union all select 'Strasser','cukor','Пётр') zw ^dc.test1D w !,"---- Before (for all indexes by default = 'Cache standard') --------",!! d print w !,"---- After (each index has its own collation) --------",!! d ..%PurgeIndices() d $system.OBJ.DisplayError(##class(%GlobalEdit).Create(,"dc.test1.iDE",##class(%Collate).DisplayToLogical("German3"))) ,$system.OBJ.DisplayError(##class(%GlobalEdit).Create(,"dc.test1.iHU",##class(%Collate).DisplayToLogical("Hungarian1"))) ,$system.OBJ.DisplayError(##class(%GlobalEdit).Create(,"dc.test1.iRU",##class(%Collate).DisplayToLogical("Cyrillic4"))) ,..%BuildIndices(,$$$NO,$$$YES,$$$NO) ,$system.SQL.TuneTable($classname(),$$$YES) ,$system.OBJ.Compile($classname(),"cu-d") ,print q print zw ^dc.test1.iDE,^dc.test1.iHU,^dc.test1.iRU w ! f lng="DE","HU","RU" d ##class(%SQL.Statement).%ExecDirect(,$$$FormatText("select %ID,Desc%1 from dc.test1 order by %exact(Desc%1)",lng)).%Display() w !! q } Storage Default { <Data name="test1DefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> <Value name="2"> <Value>DescDE</Value> </Value> <Value name="3"> <Value>DescHU</Value> </Value> <Value name="4"> <Value>DescRU</Value> </Value> </Data> <DataLocation>^dc.test1D</DataLocation> <DefaultData>test1DefaultData</DefaultData> <IdLocation>^dc.test1D</IdLocation> <Index name="iDE"> <Location>^dc.test1.iDE</Location> </Index> <Index name="iHU"> <Location>^dc.test1.iHU</Location> </Index> <Index name="iRU"> <Location>^dc.test1.iRU</Location> </Index> <IndexLocation>^dc.test1I</IndexLocation> <StreamLocation>^dc.test1S</StreamLocation> <Type>%Library.CacheStorage</Type> } }Result: USER>d ##class(dc.test1).Test() ^dc.test1D=3 ^dc.test1D(1)=$lb("","Straßer","csak","Прохор") ^dc.test1D(2)=$lb("","Straster","comb","Павел") ^dc.test1D(3)=$lb("","Strasser","cukor","Пётр") ---- Before (for all indexes by default = 'Cache standard') -------- ^dc.test1.iDE("Strasser",3)="" ^dc.test1.iDE("Straster",2)="" ^dc.test1.iDE("Straßer",1)="" ^dc.test1.iHU("comb",2)="" ^dc.test1.iHU("csak",1)="" ^dc.test1.iHU("cukor",3)="" ^dc.test1.iRU("Павел",2)="" ^dc.test1.iRU("Прохор",1)="" ^dc.test1.iRU("Пётр",3)="" ID DescDE 3 Strasser 2 Straster 1 Straßer 3 Rows(s) Affected ID DescHU 2 comb 1 csak 3 cukor 3 Rows(s) Affected ID DescRU 2 Павел 1 Прохор 3 Пётр 3 Rows(s) Affected ---- After (each index has its own collation) -------- ^dc.test1.iDE("Strasser",3)="" ^dc.test1.iDE("Straßer",1)="" ^dc.test1.iDE("Straster",2)="" ^dc.test1.iHU("comb",2)="" ^dc.test1.iHU("cukor",3)="" ^dc.test1.iHU("csak",1)="" ^dc.test1.iRU("Павел",2)="" ^dc.test1.iRU("Пётр",3)="" ^dc.test1.iRU("Прохор",1)="" ID DescDE 3 Strasser 1 Straßer 2 Straster 3 Rows(s) Affected ID DescHU 2 comb 3 cukor 1 csak 3 Rows(s) Affected ID DescRU 2 Павел 3 Пётр 1 Прохор 3 Rows(s) Affected Class dc.test2 Extends %Persistent { Index iDE On (Lng, Descr As EXACT); Index iHU On (Lng, Descr As EXACT); Index iRU On (Lng, Descr As EXACT); Property Lng As %String; Property Descr As %String; /// d ##class(dc.test2).Test() ClassMethod Test() { d ..%KillExtent() ,$system.OBJ.DisplayError(##class(%GlobalEdit).Create(,"dc.test2.iDE",##class(%Collate).DisplayToLogical("German3"))) ,$system.OBJ.DisplayError(##class(%GlobalEdit).Create(,"dc.test2.iHU",##class(%Collate).DisplayToLogical("Hungarian1"))) ,$system.OBJ.DisplayError(##class(%GlobalEdit).Create(,"dc.test2.iRU",##class(%Collate).DisplayToLogical("Cyrillic4"))) &sql(insert into dc.test2(Lng,Descr) select 'DE', 'Straßer' union select 'DE', 'Straster' union select 'DE', 'Strasser' union select 'HU', 'csak' union select 'HU', 'comb' union select 'HU', 'cukor' union select 'RU', 'Прохор' union select 'RU', 'Павел' union select 'RU', 'Пётр') zw ^dc.test2D,^dc.test2.iDE,^dc.test2.iHU,^dc.test2.iRU d $system.SQL.TuneTable($classname(),$$$YES) ,$system.OBJ.Compile($classname(),"cu-d") ,print q print w ! f lng="DE","HU","RU" { s idx=$replace("iDE,iHU,iRU","i"_lng,"_i"_lng) d ##class(%SQL.Statement).%ExecDirect(,$$$FormatText("select * from %IGNOREINDEX %1 dc.test2 where Lng=? order by %exact(Descr)",idx),lng).%Display() w !! } q } Storage Default { <Data name="test2DefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> <Value name="2"> <Value>Lng</Value> </Value> <Value name="3"> <Value>Descr</Value> </Value> </Data> <DataLocation>^dc.test2D</DataLocation> <DefaultData>test2DefaultData</DefaultData> <IdLocation>^dc.test2D</IdLocation> <Index name="iDE"> <Location>^dc.test2.iDE</Location> </Index> <Index name="iHU"> <Location>^dc.test2.iHU</Location> </Index> <Index name="iRU"> <Location>^dc.test2.iRU</Location> </Index> <IndexLocation>^dc.test2I</IndexLocation> <StreamLocation>^dc.test2S</StreamLocation> <Type>%Library.CacheStorage</Type> } }Result: USER>d ##class(dc.test2).Test() ^dc.test2D=9 ^dc.test2D(1)=$lb("","DE","Straßer") ^dc.test2D(2)=$lb("","DE","Straster") ^dc.test2D(3)=$lb("","DE","Strasser") ^dc.test2D(4)=$lb("","HU","csak") ^dc.test2D(5)=$lb("","HU","comb") ^dc.test2D(6)=$lb("","HU","cukor") ^dc.test2D(7)=$lb("","RU","Прохор") ^dc.test2D(8)=$lb("","RU","Павел") ^dc.test2D(9)=$lb("","RU","Пётр") ^dc.test2.iDE(" DE","Strasser",3)="" ^dc.test2.iDE(" DE","Straßer",1)="" ^dc.test2.iDE(" DE","Straster",2)="" ^dc.test2.iDE(" HU","comb",5)="" ^dc.test2.iDE(" HU","csak",4)="" ^dc.test2.iDE(" HU","cukor",6)="" ^dc.test2.iDE(" RU","Павел",8)="" ^dc.test2.iDE(" RU","Прохор",7)="" ^dc.test2.iDE(" RU","Пётр",9)="" ^dc.test2.iHU(" DE","Strasser",3)="" ^dc.test2.iHU(" DE","Straster",2)="" ^dc.test2.iHU(" DE","Straßer",1)="" ^dc.test2.iHU(" HU","comb",5)="" ^dc.test2.iHU(" HU","cukor",6)="" ^dc.test2.iHU(" HU","csak",4)="" ^dc.test2.iHU(" RU","Павел",8)="" ^dc.test2.iHU(" RU","Прохор",7)="" ^dc.test2.iHU(" RU","Пётр",9)="" ^dc.test2.iRU(" DE","Strasser",3)="" ^dc.test2.iRU(" DE","Straster",2)="" ^dc.test2.iRU(" DE","Straßer",1)="" ^dc.test2.iRU(" HU","comb",5)="" ^dc.test2.iRU(" HU","csak",4)="" ^dc.test2.iRU(" HU","cukor",6)="" ^dc.test2.iRU(" RU","Павел",8)="" ^dc.test2.iRU(" RU","Пётр",9)="" ^dc.test2.iRU(" RU","Прохор",7)="" ID Descr Lng 3 Strasser DE 1 Straßer DE 2 Straster DE 3 Rows(s) Affected ID Descr Lng 5 comb HU 6 cukor HU 4 csak HU 3 Rows(s) Affected ID Descr Lng 8 Павел RU 9 Пётр RU 7 Прохор RU 3 Rows(s) Affected Important: if you remove "As EXACT" in the index, the examples will not work correctly for the German language, because: Capital ẞ
go to post Vitaliy Serdtsev · Jun 15, 2018 Add the RenderDirectlyOnTimeout property in the report: Property RenderDirectlyOnTimeout As %ZEN.Datatype.boolean(ZENURL = "$RENDERDIRECTLYONTIMEOUT") [ InitialExpression = {$$$NO} ];Then you will get the following error: ERROR #5001: Cannot contact server on port %1.or ERROR #5001: Received Control-C or there was a fatal error.
go to post Vitaliy Serdtsev · Jun 14, 2018 Suppose there is such a code: int caseSwitch = 1; switch (caseSwitch) { case 1: Console.WriteLine("Case 1"); //a lot of code break; case 2: case 8-9: Console.WriteLine("Case 2 or 8 or 9"); //a lot of code break; case 3: Console.WriteLine("Case 3"); //a lot of code break; /*... a lot conditions ...*/ default: Console.WriteLine("Default case"); //a lot of code break; }In this case $select;if/elseif/else is not effective because for last conditions will have to iterate through all the previous ones $case is redundant: you will have to specify the same code multiple times for different values For this particular case, I suggest using a transition table, for example: ClassMethod Test(caseSwitch = 3) [ ProcedureBlock = 0 ] { s:'$d(^||addr) ^||addr(1)=1, (^(2),^(8),^(9))=289, ^(3)=3 d @("case"_$g(^||addr(caseSwitch),"def")) q case1 w "Case 1" q case289 w "Case 2 or 8 or 9" q case3 w "Case 3" q casedef w "Default case" q }Of course, you can modify the example to call procedures, functions, class methods, etc.
go to post Vitaliy Serdtsev · Jun 13, 2018 Yes, of course: Projection of Packages to Schemas Relational View of Object Features
go to post Vitaliy Serdtsev · Jun 13, 2018 You can change the XSLFO Stylesheet dynamically or statically. See XSLFOSTYLESHEET So, there is a class-report, for example MyApp.ReportDemo. Series of steps: remove option XSLFOSTYLESHEET, if any, and recompile class generate XSLFO Stylesheet: SAMPLES>d $system.OBJ.DisplayError(##class(MyApp.ReportDemo).GenerateToFile($system.CSP.GetFileName($system.CSP.GetDefaultApp($zu(5))_"/MyApp.ReportDemo.xsl"),4)) make changes to MyApp.ReportDemo.xsl add the parameter XSLFOSTYLESHEET and recompile the class again /// If defined, this provides a reference to the external /// stylesheet to use in generating the XSL-FO (PDF) report. /// If it is not provided, a stylesheet will be generated /// from the ReportDisplay XData block. Parameter XSLFOSTYLESHEET As String = "MyApp.ReportDemo.xsl"; Now open the report in your browser/command line/etc. Profit! Important: if you change something in ReportDisplay, you need to repeat the steps again.
go to post Vitaliy Serdtsev · Jun 12, 2018 Page numbering in Roman Numerals Need add the attribute format to the element <fo:page-sequence>, i.e. <fo:page-sequence master-reference='blablabla' format ='I' .. >Possible value format: format="1" results in 1 2 3 . . format="01" results in 01 02 03 format="a" results in a b c . . format="A" results in A B C. . format="i" results in i ii iii iv . . format="I" results in I II III IV . . more.. Example: Do all the steps according to Zen Report Tutorial Insert the page number into <pagefooter> <!-- Optional Pagefooter element. Does not apply in HTML output. --> <pagefooter> <item special="page-number"/> </pagefooter> Insert the following code into the class: ClassMethod ReplaceStream( ByRef stream As %Stream.TmpBinary, format) [ Private ] { s tmp=##class(%Stream.TmpBinary).%New() while 'stream.AtEnd { d tmp.Write($replace(stream.Read($$$MaxLocalLength),"<fo:page-sequence ",$$$FormatText("<fo:page-sequence format=%1 ",$$$quote(format)))) } d stream.CopyFrom(tmp) } /// d ##class(MyApp.ReportDemo).Test() ClassMethod Test(format = "1") { /* •0 = XML •1 = HTML •2 = PDF •3 = ToHTML Stylesheet •4 = ToXSLFO Stylesheet •5 = XSD Schema •6 = PrintPS •7 = Excel •8 = XSLFO •9 = ToEXCEL •10=xlsx •11=TIFF •12=pdfprint •13=displayxlsx •14=fo2pdf •15=foandpdf */ s xslfo=##class(%Stream.TmpBinary).%New() s t=..%New() d t.GenerateReportToStream(.xslfo,4) d ..ReplaceStream(.xslfo,format) s t.toxslfostream=xslfo d $system.OBJ.DisplayError(t.GenerateReport("c:\temp\test.pdf",2)) } SAMPLES>d ##class(MyApp.ReportDemo).Test("I") or SAMPLES>d ##class(MyApp.ReportDemo).Test("01") or SAMPLES>d ##class(MyApp.ReportDemo).Test("A") open test.pdf. Profit!
go to post Vitaliy Serdtsev · May 28, 2018 Try so: <tabGroup ... onshowTab="zenThis.refreshContents(true);"> </tabGroup>
go to post Vitaliy Serdtsev · May 8, 2018 HOWTO: DER vs. CRT vs. CER vs. PEM Certificates and How To Convert Them
go to post Vitaliy Serdtsev · May 7, 2018 USER>w $zv Cache for Windows (x86-32) 2015.2 (Build 664_3U) Wed Aug 12 2015 12:29:34 EDTThe date is saved to the database correctly. Class dc.A Extends %Persistent { Property DOB As %Date; } Class dc.MVC.A Extends %ZEN.DataModel.ObjectDataModel { Property DOB As %Date(ZENATTRS = "id:DOB|format:DMY|separator:/", ZENCONTROL = "dateText"); Method %OnNewSource(Output pSC As %Status = {$$$OK}) As %RegisteredObject { q ##class(dc.A).%New() } Method %OnOpenSource( pID As %String, pConcurrency As %Integer = -1, Output pSC As %Status = {$$$OK}) As %RegisteredObject { q ##class(dc.A).%OpenId(pID,pConcurrency,.pSC) } Method %OnSaveSource(pSource As dc.A) As %Status { q pSource.%Save() } ClassMethod %OnDeleteSource(pID As %String) As %Status { q ##class(dc.A).%DeleteId(pID) } Method %OnLoadModel(pSource As dc.A) As %Status { s ..DOB = pSource.DOB q $$$OK } Method %OnStoreModel(pSource As dc.A) As %Status { s pSource.DOB = ..DOB q $$$OK } } Class dc.test Extends %ZEN.Component.page { XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen"> <dataController id="a-controller" modelClass="dc.MVC.A" modelId=""/> <dynaForm id="a-form" controllerId="a-controller"/> <button caption="Save" onclick="zen('a-form').save();" /> </page> } }
go to post Vitaliy Serdtsev · Apr 14, 2018 %PosixTime %PosixTime is preferable to %TimeStamp, because it takes up less disk space and memory than the %TimeStamp data type and provides better performance than %TimeStamp.proof
go to post Vitaliy Serdtsev · Apr 6, 2018 My best result is 77 72 69 67 so far. Class ITPlanet.Task4 [ Abstract ] { ClassMethod main(s As %Integer = 10) { f x=1:1:s w ! f y=1:1:s w $c(y#s<2!$lf($lb(1,s,y,s-y+1),x)*3+32) } ClassMethod length( class = {$classname()}, method = "main") As %Integer [ CodeMode = expression ] { ##class(%Dictionary.MethodDefinition).IDKEYOpen(class, method).Implementation.Size } } USER>w ##class(ITPlanet.Task4).length() 67 USER>d ##class(ITPlanet.Task4).main(11) ########### ## ## # # # # # # # # # # # # # # # # # # # # # # # # # # # ## ## ###########
go to post Vitaliy Serdtsev · Mar 27, 2018 Make two changes to your code: /// return json Method infoJson() As %String [ WebMethod ] { set soapresponse=##class(webservice.SOAPResponse).%New() set soapresponse.CustomerID="1" set soapresponse.Name="2" set soapresponse.Street="3" set soapresponse.City="4" set soapresponse.State="5" set soapresponse.Zip="6" set stream=##class(%Stream.TmpBinary).%New() do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(stream,soapresponse,,,$$$YES,"s") quit stream.Read($$$MaxStringLength) } /// write ##class(PRD.Test).test1() ClassMethod test1() As %String { set soapresponse=##class(webservice.SOAPResponse).%New() set soapresponse.CustomerID="1" set soapresponse.Name="2" set soapresponse.Street="3" set soapresponse.City="4" set soapresponse.State="5" set soapresponse.Zip="6" set stream=##class(%Stream.TmpBinary).%New() do ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(stream,soapresponse,,,$$$YES,"s") quit stream.Read($$$MaxStringLength) }
go to post Vitaliy Serdtsev · Dec 29, 2017 Undefined variable and the variable contains "" (null) is two different situations, e.g. (see $DATA): kill myObj write $data(myObj),! ; -> 0 set myObj=$$$NULLOREF write $data(myObj),! ; -> 1In your case it would be better to use $IsObject: kill myObj write $IsObject(myObj),! ; -> 0 set d=$$$NULLOREF write $IsObject(myObj),! ; -> 0 set myObj={} write $IsObject(myObj),! ; -> 1Accordingly, should be do $$$AssertTrue('$IsObject(myObj), "myObj is null")
go to post Vitaliy Serdtsev · Dec 26, 2017 Here's another way (without PlaceAfter): Class Macro.Child Extends Macro.Parent { ClassMethod %inc() [ Internal, Private ] { #include Child } ClassMethod Test() { write "Class: " , $classname() , ! , "Value: " , $$$name } }
go to post Vitaliy Serdtsev · Dec 14, 2017 select DOB from sample.person -- or HSAA.Patient where (tochar(current_date,'YYYYMMDD')-tochar(DOB,'YYYYMMDD'))\10000>=13 or ((year(current_date)||'1231')-tochar(DOB,'YYYYMMDD'))\10000=13
go to post Vitaliy Serdtsev · Dec 5, 2017 See Sample.Person in "SAMPLES". /// Person's age.<br> /// This is a calculated field whose value is derived from <property>DOB</property>. Property Age As %Integer [ Calculated, SqlComputeCode = { Set {Age}=##class(Sample.Person).CurrentAge({DOB})}, SqlComputed, SqlComputeOnChange = DOB ]; /// This class method calculates a current age given a date of birth <var>date</var>. ClassMethod CurrentAge(date As %Date = "") As %Integer [ CodeMode = expression ] { $Select(date="":"",1:($ZD($H,8)-$ZD(date,8)\10000)) }