Pesquisar

Pergunta
· Jul. 27

How to Calculate Time Differences in Hours Between Two Timestamps in ObjectScript?

Hi all,

I’m working on a data transformation in IRIS where I need to calculate the difference in hours between two timestamps stored as %TimeStamp.

Example:

Set startTime = "2024-07-12 08:30:00"
Set endTime = "2024-07-12 15:15:00"

I’d like to calculate the number of hours (with decimals, like 6.75) between them. What's the recommended way to do this in ObjectScript? I’ve seen examples using $ZDATETIME, but I’m not sure if that’s the cleanest approach.

Any suggestions or best practices would be appreciated!

Thanks,
Jhonn Marie

3 Comments
Discussão (3)3
Entre ou crie uma conta para continuar
Artigo
· Jul. 27 2min de leitura

Reviews on Open Exchange - #54

If one of your packages on OEX receives a review you get notified by OEX only of YOUR own package.   
The rating reflects the experience of the reviewer with the status found at the time of review.   
It is kind of a snapshot and might have changed meanwhile.   
Reviews by other members of the community are marked by * in the last column.

I also placed a bunch of Pull Requests on GitHub when I found a problem I could fix.    
Some were accepted and merged, and some were just ignored.     
So if you made a major change and expect a changed review, just let me know.

# Package Review Stars IPM Docker *
1 iris-python-article excellent 6* 6.0   y  
2 iris4word Super Package 6* 6.0 y y  
3 Global-Inspector finally globals + COS + CSP 5.0 y   *
4 iris-telemetry-sample great demo 5.0   y  
5 metabase-iris-driver attractive add-on 5.0   y  
6 templated_email well prepared 5.0 y y  
7 typeorm-iris impressive solution 5.0   y  
8 wsgi-to-zpm great tool 5.0 y y  
9 dc-artisan docker part runs fine 4.8 y y  
10 IrisTest now working as described 4.8 y y  
11 iris-message-search looks friendly 4.7 y y  
12 toolqa incomplete yet 3.8   y  
13 addsearchtable useful idea 3.7 y y  
14 iristest-html a nice idea 3.5 y    
15 PyObjectscript Gen mostly working 3.0      
2 Comments
Discussão (2)2
Entre ou crie uma conta para continuar
Artigo
· Jul. 27 4min de leitura

Inovando por uma Elegância Generativa

Público

Aqueles interessados em explorar novos casos de uso da IA Generativa

Compartilha ideias e a lógica por trás do treinamento de IA generativa para reconhecimento de padrões.

Desafio 1 - Simples, mas não simplista

Um desenvolvedor aspira a conceber uma solução elegante para requisitos. O reconhecimento de padrões (como expressões regulares) pode ser resolvido de várias maneiras. Qual delas é a melhor solução de código?

Uma IA pode postular uma solução elegante de reconhecimento de padrões para uma variedade de amostras de dados, do simples ao complexo?

Considere os três valores de string:

  • "AA"
  • "BB"
  • "CC"

A expressão: "2 caracteres alfabéticos" corresponde a todos esses valores e a outros valores intuitivamente semelhantes de forma geral e flexível.

Alternativamente, a expressão: "AA" ou "BB" ou "CC" seria uma forma muito específica de corresponder apenas a estes valores:

Outra forma de resolver seria: "A" ou "B" ou "C", duas vezes.

Desafio 2 - Amostra incompleta

Os problemas de padrões raramente têm todos os exemplos especificados. Uma IA performática precisa aceitar uma amostra limitada e incompleta de linhas de dados e postular uma expressão de reconhecimento de padrões razoável.

Um objetivo de Turing seria atingir a paridade com a inferência humana para um padrão de dados representativos, mas incompletos.

Uma melhor qualidade de processamento de amostras é uma prioridade maior do que expandir a janela de tokens para amostras maiores.

 

Desafio 3 - Aproveitando sequências repetidas

Estendendo o exemplo anterior, para incluir também valores de um único caractere.

  • "A"
  • "B"
  • "C"

Isso parece mais elegante do que especificar TODOS os valores possíveis por extenso.

 if test?1(1"A",1"B",1"C",1"AA",1"BB",1"CC")

 

Desafio 4 - Vício em dados delimitados

Uma necessidade comum, além de padrões generalizados, é resolver dados delimitados. Por exemplo, um formato de número de telefone aleatório:

213-5729-57986

Poderia ser resolvido pela expressão:
3 numéricos, traço, 4 numéricos, traço, 4 numéricos

 if test?3N1"-"4N1"-"4N

Isso pode ser normalizado com a sequência de repetição para:

 if test?3N2(1"-"4)

Essencialmente, isso significa ter uma preferência por especificar explicitamente um delimitador, por exemplo "-", em vez de generalizar os delimitadores como caracteres de pontuação. Assim, a saída gerada deve preferir evitar a supergeneralização, por exemplo:

 if test?3N1P4N1P4N

 

Desafio 5 - Sequências repetidas

Considere números formatados com códigos de prefixo comuns.

O modelo de IA detecta três sequências comuns nos valores e direciona a solução para refletir um interesse nesse recurso:

Nesta ocasião, a IA decidiu gerar uma correspondência de string "13" supérflua.

No entanto, conforme indicado pela ferramenta, o padrão corresponderá a todos os valores fornecidos.

O padrão pode ser facilmente ajustado na descrição de texto livre e regenerado.

Velocidade de inferência

A assistência da Workbench AI com sucesso parcial qualificado pode ser um acelerador para a implementação.

Acima de um certo limite de complexidade, um assistente de IA pode deduzir propostas mais rapidamente do que a análise manual.

Considere a seguinte tentativa de inferência de IA com sucesso parcial qualificado:

O assistente de IA usa o maior número de linhas de dados que consegue encaixar em sua janela de contexto de tokens para processamento, pulando o excesso de linhas de dados.

O número de linhas é quantificado na saída gerada, mostrando como os dados foram truncados para a inferência.

Isso pode ser útil para elevar as linhas de dados preferidas de volta à janela de contexto para um reprocessamento refinado.

 

Esforço de treinamento

ndo como alvo a GPU Nvidia Cuda A10 no Huggingface.

Treinamento de modelo supervisionado.

Estágio Treinamento contínuo da GPU
Protótipo do conjunto de dados de base 4 dias
Conjunto de dados principal 13 dias
Segundo conjunto de dados refinado 2 dias

 

Conclusão

A inferência generativa de disparo único com tamanho de token limitado pode abordar de forma útil a elegância da solução de código discreto na ausência de processamento "chain-of-thought", selecionando o viés do especialista no assunto nos dados de treinamento de base.

Os assistentes de IA podem participar em fluxos de trabalho de solução iterativos.

 

Saiba mais

Experimente a demonstração de tecnologia atualmente hospedada via Huggingface. O símbolo de engrenagem nos botões da demonstração indica onde a geração de IA está sendo empregada.

Demonstração escrita para o público de inglês, francês e espanhol.

Discussão (0)1
Entre ou crie uma conta para continuar
Discussão (0)1
Entre ou crie uma conta para continuar
Artigo
· Jul. 26 8min de leitura

Creating advanced Word documents with IRIS

Word documents are widely used in the market. Users frequently create contracts, memos, resumes, reports, analyses, and other documents that may require data from or captured by InterSystems IRIS. However, IRIS does not have an API, SDK, library, or adapter for this. This limitation no longer exists. 

The new Open Exchange library iris4word (https://openexchange.intersystems.com/package/iris4word) delivers an ObjectScript SDK where the developer passes any %DynamicObject as a parameter, a Word file template and then receives a ready document, with the structure and formatting defined in its template.


To use iris4word

This article will use a REST API to get the content, but it is possible query database also. To install the iris4word and the sample using it, proceed with these tasks:

  1. If you use IPM/ZPM: zpm:USER>install iris4word
  2. If you use Docker: 
    1. git clone https://github.com/yurimarx/iris4word.git
    2. docker-compose up -d --build
  3. Open the Postman (to execute the REST API sample)
  4. Import the sample collection from (https://raw.githubusercontent.com/yurimarx/iris4word/refs/heads/master/iris4word.postman_collection.json): 
  5. Upload the file template template.docx (in the sample/template.docx path of this repository or from https://raw.githubusercontent.com/yurimarx/iris4word/refs/heads/master/sample/template.docx). To upload, fill the file field into the Body tab: 
  6.  The upload process will send the template to the server to be used by the iris4word.
  7. Open the 2. Download Word Document and copy and past to the body this JSON content: 
    {
      "company": {
        "name": "ACM Ltda.",
        "address": "Main Street, 123",
        "city": "New York",
        "state": "NY"
      },
      "projects": [
        {
          "name": "System Development X",
          "beginDate": "2024-01-01",
          "endDate": "2024-06-06",
          "team": [
            {"name": "John Star", "role": "Senior Developer"},
            {"name": "Marie Loo", "role": "BDM"}
          ],
          "tasks": [
            {"description": "Requirements", "status": "Done"},
            {"description": "Development", "status": "Doing"}
          ]
        },
        {
          "name": "ERP Development Y",
          "beginDate": "2024-03-03",
          "endDate": "2025-12-12",
          "team": [
            {"name": "Peter Rogers", "role": "Project Manager"},
            {"name": "Robert Plant", "role": "ERP Specialist"}
          ],
          "tasks": [
            {"description": "ERP configuration", "status": "Done"},
            {"description": "User training", "status": "Doing"}
          ]
        }
      ],
      "principalContact": {
        "name": "Carlos Olivera",
        "email": "carlos.olivera@company.com",
        "phone": "+1 555 555-555"
      }
    }
     
  8. On the Send button, select the option Send and Download:
  9. See the results:
  10. Compare the JSON content with the template.docx and see the marks and tags used.

Behind the Scenes

It's very easy, with the template file saved into /tmp/template.docx, just call it:

ClassMethod DownloadDoc(template As %String) As %Status
{
    Set tUUID = $System.Util.CreateGUID() 
    Set filePath = "/tmp/"_tUUID_".docx"
    Set jsonContentString = {}.%FromJSON(%request.Content)
    Set sc = ##class(dc.iris4word.WordUtil).GenerateWordFileFromJSON(jsonContentString.%ToJSON(), "/tmp/"_template_".docx", filePath)

    Set %response.NoCharSetConvert=1
    Set %response.Headers("Access-Control-Allow-Origin")="*"
    Do %response.SetHeader("Content-Type","application/vnd.openxmlformats-officedocument.wordprocessingml.document")
    Do %response.SetHeader("Content-Disposition","attachment;filename="""_tUUID_".docx"_"""")
    
    Set stream=##class(%Stream.FileBinary).%New()
    Set sc=stream.LinkToFile(filePath)
    Do stream.OutputToDevice()
    
    Return sc
}

O ClassMethod ##class(dc.iris4word.WordUtil).GenerateWordFileFromJSON recebe os dados na forma de um %DynamicObject, the word template path and the file path where the final word document must be created. Now you have a word file to send to the user as response. Very easy!!

The Template language

The iris4word delivers to you a flexible template language to compose dynamic word documents using the Microsoft Word editor.

Text tag

The text tag is the most basic tag type in the Word template. {{name}} will be replaced by the value of key name in the data model. If the key is not exist, the tag will be cleared(The program can configure whether to keep the tag or throw an exception).

Template:

{{name}} always said life was like a box of {{thing}}.

Output:

Mama always said life was like a box of chocolates.

Picture tag

The image tag starts with @, for example, {{@logo}} will look for the value with the key of logo in the data model, and then replace the tag with the image. The data corresponding to the image tag can be a simple URL or Path string, or a structure containing the width and height of the image.

Template:

Fruit Logo:
watermelon {{@watermelon}}
lemon {{@lemon}}
banana {{@banana}}
Output:

Fruit Logo:
watermelon 🍉
lemon 🍋
banana 🍌

Numbering

The list tag corresponds to Word's symbol list or numbered list, starting with *, such as {{*number}}.

Template:

{{*list}}
Output:

● Plug-in grammar
● Supports word text, pictures, table...
● Templates, not just templates, but also style templates

Sections

A section is composed of two tags before and after, the start tag is identified by ?, and the end tag is identified by /, such as {{?section}} as the start tag of the sections block, {{/section} } is the end tag, and section is the name of this section.

Sections are very useful when processing a series of document elements. Document elements (text, pictures, tables, etc.) located in a section can be rendered zero, one or N times, depending on the value of the section.

False Values or Empty collection

If the value of the section is null, false or an empty collection, all document elements located in the section will not be displayed, similar to the condition of the if statement is false.

Datamodel:

{
  "announce": false
}
Template:

Made it,Ma!{{?announce}}Top of the world!{{/announce}}
Made it,Ma!
{{?announce}}
Top of the world!🎋
{{/announce}}
Output:

Made it,Ma!
Made it,Ma!

Non-False Values and Not a collection

If the value of the section is not null, false, and is not a collection, all document elements in the section will be rendered once, similar to the condition of the if statement is true.

Datamodel:

{
  "person": { "name": "Sayi" }
}
Template:

{{?person}}
  Hi {{name}}!
{{/person}}
Output:

  Hi Sayi!

Non-Empty collection

If the value of the section is a non-empty collection, the document elements in the section will be looped once or N times, depending on the size of the collection, similar to the foreach syntax.

Datamodel:

{
  "songs": [
    { "name": "Memories" },
    { "name": "Sugar" },
    { "name": "Last Dance" }
  ]
}
Template:

{{?songs}}
{{name}}
{{/songs}}
Output:

Memories
Sugar
Last Dance
In the loop, a special tag {{=#this}} can be used to directly refer to the object of the current iteration.

Datamodel:

{
  "produces": [
    "application/json",
    "application/xml"
  ]
}
Template:

{{?produces}}
{{=#this}}
{{/produces}}
Output:

application/json
application/xml

The Java code developed to create the iris4word library

The iris4word was created using Java. The InterSystems IRIS supports use Java libraries with External Java Gateway feature:

ClassMethod GenerateWordFileFromJSON(jsonContent As %String, wordTemplateFileName As %String, wordFileName As %String) As %Status
{
    Set tSC = $$$OK

    Try {
        
        set javaGate = $system.external.getJavaGateway()  
        do javaGate.addToPath($SYSTEM.Util.BinaryDirectory()_"iris4word-1.0.0-jar-with-dependencies.jar")
        set wordUtil = javaGate.new("iris4word.WordUtil")
...
}

The instruction $system.external.getJavaGateway returned a Java engine and the addToPath allow us to use the file iris4word-1.0.0.0-jar-with-dependencies.jar. This library has the iris4word implementation:

package iris4word;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.io.IOException;
import java.util.Map;

public class WordUtil {

    public void createFromFile(String jsonFileName, String wordTemplateFileName, String wordFileName) {
        
    	java.util.logging.Logger julLogger2 = java.util.logging.Logger.getLogger("com.deepoove.poi.render.processor.LogProcessor");
    	julLogger2.setLevel(java.util.logging.Level.OFF);
    	
    	java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("org.slf4j.Logger");
        julLogger.setLevel(java.util.logging.Level.OFF);
        
    	ObjectMapper objectMapper = new ObjectMapper(); 
    	XWPFTemplate template = null;
    	
        try {
            File jsonFile = new File(jsonFileName);
            
            @SuppressWarnings("unchecked")
			Map<String, Object> data = objectMapper.readValue(jsonFile, Map.class);

            Configure config = Configure.builder().build();

            template = XWPFTemplate.compile(wordTemplateFileName, config).render(data);

            template.writeToFile(wordFileName);
            

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
        	if(template != null) {        		
        		try {
					template.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
        	}
		}
    }
	
}

The iris4word used the open source library poi-tl (package com.deepoove.poi) to render word templates with dynamic data. The iris4word transform JSON data to the poi-tl format, set the data to poi-tl, execute the rendering process and get the word document. The document is saved to the disk to be used into ObjectScript code:

ClassMethod GenerateWordFile(jsonFileName As %String, wordTemplateFileName As %String, wordFileName As %String) As %Status
{
    Set tSC = $$$OK

    Try {
        
        set javaGate = $system.external.getJavaGateway()  
        do javaGate.addToPath($SYSTEM.Util.BinaryDirectory()_"iris4word-1.0.0-jar-with-dependencies.jar")
        set wordUtil = javaGate.new("iris4word.WordUtil") 
        
        do wordUtil.createFromFile(jsonFileName, wordTemplateFileName, wordFileName)
        
    }
    Catch ex {
        Set tSC=ex.AsStatus()
    }

    return tSC
}

This project demonstrates how not only Python, but also Java, can significantly extend IRIS's functionality. Enjoy!

2 Comments
Discussão (2)1
Entre ou crie uma conta para continuar