T4.4: Mathematical, Logical, and Date/Time Operations

Knowledge Review - InterSystems ObjectScript Specialist

1. Operadores matemáticos

Puntos Clave

  • Operadores básicos: + (sumar), - (restar), * (multiplicar), / (dividir)
  • División entera (\\): Trunca a entero: 7 \\ 2 = 3
  • Módulo (#): Residuo: 7 # 3 = 1
  • Exponenciación (**): Potencia: 2 ** 3 = 8
  • ESTRICTAMENTE DE IZQUIERDA A DERECHA: Sin precedencia de operadores. 2 + 3 * 4 = 20, NO 14
  • Se requieren paréntesis: Use paréntesis para forzar el orden deseado: 2 + (3 * 4) = 14
  • Menos unario: Prefijo menos para negación: SET x = -5

Notas Detalladas

Descripción general

ObjectScript evalúa expresiones matemáticas estrictamente de izquierda a derecha SIN precedencia de operadores. Esta es una de las diferencias más importantes con otros lenguajes y una fuente frecuente de errores para desarrolladores que vienen de C, Java o Python. La única forma de cambiar el orden de evaluación es con paréntesis.

Evaluación de izquierda a derecha (FUNDAMENTAL)

 // In most languages: 2 + 3 * 4 = 14 (multiplication first)
 // In ObjectScript:   2 + 3 * 4 = 20 (left to right!)

 WRITE 2 + 3 * 4, !           // 20  (5 * 4, NOT 2 + 12)
 WRITE 2 + (3 * 4), !         // 14  (parentheses force multiplication first)

 WRITE 10 - 2 * 3, !          // 24  ((10-2) * 3)
 WRITE 10 - (2 * 3), !        // 4   (10 - 6)

 WRITE 12 / 3 + 1, !          // 5   ((12/3) + 1)
 WRITE 12 / (3 + 1), !        // 3   (12 / 4)

 // Complex example
 WRITE 2 + 3 * 4 - 1, !       // 19  (((2+3)*4)-1)
 WRITE 2 + (3 * (4 - 1)), !   // 11  (2 + 9)

Aritmética básica

 SET a = 10, b = 3

 WRITE a + b, !                // 13
 WRITE a - b, !                // 7
 WRITE a * b, !                // 30
 WRITE a / b, !                // 3.333333333333333333

 // Integer division (truncates toward zero)
 WRITE 7 \ 2, !                // 3
 WRITE -7 \ 2, !               // -3
 WRITE 10 \ 3, !               // 3

 // Modulo (remainder)
 WRITE 7 # 3, !                // 1
 WRITE 10 # 4, !               // 2
 WRITE 15 # 5, !               // 0

 // Exponentiation
 WRITE 2 ** 3, !               // 8
 WRITE 3 ** 2, !               // 9
 WRITE 10 ** 0, !              // 1
 WRITE 4 ** 0.5, !             // 2 (square root)

Patrones prácticos

 // Check if number is even
 SET n = 42
 IF n # 2 = 0 WRITE n, " is even", !

 // Round to 2 decimal places
 SET price = 19.99 * 1.0825     // tax calculation
 SET rounded = $JUSTIFY(price, 0, 2)
 WRITE rounded, !               // 21.64

 // Always use parentheses for clarity!
 SET total = (quantity * price) + (quantity * price * taxRate)
 SET average = sum / count
 SET circumference = 2 * (3.14159 * radius)

Coerción de cadena a número

 // ObjectScript coerces strings to numbers for arithmetic
 WRITE "5" + 3, !              // 8
 WRITE "abc" + 3, !            // 3  ("abc" = 0 numerically)
 WRITE "10xyz" + 5, !          // 15 (leading "10" is numeric)
 WRITE "" + 5, !               // 5  ("" = 0)

Referencias de Documentación

2. Operadores lógicos

Puntos Clave

  • AND: && o & -- ambos operandos deben ser verdaderos
  • OR: || o ! (heredado) -- al menos un operando debe ser verdadero
  • NOT: ' (apóstrofo) -- negación: 'condition
  • También de izquierda a derecha: Los operadores lógicos siguen la misma regla de izquierda a derecha
  • Cortocircuito con &&/||: Las formas de doble carácter hacen cortocircuito; las de un solo carácter no
  • Operadores de comparación: = (igual), '= (no igual), < (menor), > (mayor), <= (no mayor), >= (no menor)
  • Comparación de cadenas: Usa la colación predeterminada; cadenas numéricas se comparan numéricamente

Notas Detalladas

Descripción general

Los operadores lógicos de ObjectScript también siguen una evaluación estricta de izquierda a derecha. El lenguaje proporciona operadores lógicos con cortocircuito (&&, ||) y sin cortocircuito (&, !). El operador NOT es el carácter apóstrofo ('), que también puede prefijar operadores de comparación.

Operadores lógicos

 SET x = 5, y = 10

 // AND: && (short-circuit) or & (evaluates both)
 IF (x > 0) && (y > 0) WRITE "Both positive", !
 IF (x > 0) & (y > 0) WRITE "Both positive", !

 // OR: || (short-circuit) or ! (legacy, evaluates both)
 IF (x > 100) || (y > 5) WRITE "At least one true", !

 // NOT: ' (apostrophe)
 IF 'x WRITE "x is false/zero", !         // doesn't print (x=5, truthy)
 IF '0 WRITE "0 is falsy", !              // prints

 // Short-circuit demonstration
 // With &&, second operand not evaluated if first is false
 SET obj = ""
 IF (obj '= "") && (obj.Name = "test") {
     // Safe: second part not evaluated when obj=""
 }

Operadores de comparación

 SET a = 5, b = 10

 WRITE a = b, !            // 0 (false)
 WRITE a '= b, !           // 1 (true, not equal)
 WRITE a < b, !            // 1 (true)
 WRITE a > b, !            // 0 (false)
 WRITE a <= b, !           // 1 (true, less or equal)
 WRITE a >= b, !           // 0 (false, greater or equal)

 // Note: <= means "not greater than" ('>) and >= means "not less than" ('<)
 // These are actually: '> and '<
 WRITE a '> b, !           // 1 (same as <=)
 WRITE a '< b, !           // 0 (same as >=)

Operador Contiene ([)

 SET str = "Hello World"

 // [ tests if left operand contains right operand
 IF str [ "World" WRITE "Contains 'World'", !        // prints
 IF str [ "xyz" WRITE "Contains 'xyz'", !            // does not print

 // Case-sensitive
 IF str [ "hello" WRITE "Found", !                   // does not print

Operador Follows (])

 // ] tests if left operand follows right operand in collation
 WRITE "B" ] "A", !           // 1 (B follows A)
 WRITE "A" ] "B", !           // 0
 WRITE "abc" ] "abb", !       // 1

 // ]] sorts after (string sort, strictly)
 WRITE "10" ]] "9", !         // 0 ("10" sorts before "9" as strings)

Izquierda a derecha con operadores lógicos

 // Logical operators are also left-to-right!
 SET a = 1, b = 0, c = 1

 // This evaluates as: ((a || b) && c)
 WRITE a || b && c, !         // 1

 // NOT as: (a || (b && c))
 // Use parentheses to get intended behavior
 WRITE a || (b && c), !       // 1
 WRITE (a || b) && c, !       // 1

3. $ZDATE, $ZTIME, $HOROLOG

Puntos Clave

  • $HOROLOG ($H): Fecha/hora del sistema como "días,segundos" -- días desde el 31 de diciembre de 1840; segundos desde medianoche
  • $ZDATE($ZD): Convierte fecha $H a cadena formateada: $ZD($H, format)
  • $ZDATEH($ZDH): Convierte cadena formateada de vuelta a fecha interna $H
  • $ZTIME($ZT): Convierte segundos $H a cadena de hora formateada
  • $ZTIMEH($ZTH): Convierte cadena de hora formateada de vuelta a segundos $H
  • $NOW(): Devuelve marca de tiempo UTC con fracciones de segundo
  • $ZTIMESTAMP ($ZTS): Marca de tiempo UTC en formato $HOROLOG con fracciones de segundo

Notas Detalladas

Descripción general

InterSystems IRIS almacena fechas y horas internamente usando el formato $HOROLOG: un valor de dos piezas separadas por coma donde la primera pieza es el número de días desde el 31 de diciembre de 1840, y la segunda pieza es el número de segundos desde medianoche. Todas las funciones de formato de fecha/hora convierten hacia y desde este formato interno.

Fundamentos de $HOROLOG

 // Current date and time
 WRITE $HOROLOG, !
 // Example output: 67551,45123
 // 67551 = days since 12/31/1840
 // 45123 = seconds since midnight

 // Extract date and time parts
 SET datepart = $PIECE($H, ",", 1)
 SET timepart = $PIECE($H, ",", 2)
 WRITE "Days: ", datepart, !
 WRITE "Seconds: ", timepart, !

 // $H is the shorthand for $HOROLOG
 WRITE $H, !

$ZDATE: Formato de fechas

 // Format codes:
 // 1 = MM/DD/YYYY (US format)
 // 2 = DD Mmm YYYY (e.g., 15 Jan 2025)
 // 3 = YYYY-MM-DD (ISO format)
 // 4 = DD/MM/YYYY (European format)
 // 5 = Mmm DD, YYYY (e.g., Jan 15, 2025)
 // 8 = YYYYMMDD (compact)

 SET today = $PIECE($H, ",", 1)

 WRITE $ZDATE(today, 1), !         // 01/15/2025
 WRITE $ZDATE(today, 2), !         // 15 Jan 2025
 WRITE $ZDATE(today, 3), !         // 2025-01-15
 WRITE $ZDATE(today, 4), !         // 15/01/2025
 WRITE $ZDATE(today, 5), !         // Jan 15, 2025
 WRITE $ZDATE(today, 8), !         // 20250115

 // Full $H value (includes time display with some formats)
 WRITE $ZDATE($H, 3), !            // 2025-01-15

 // With separator and year digits
 WRITE $ZDATE(today, 1, "-"), !    // 01-15-2025

$ZDATEH: Análisis de cadenas de fecha

 // Convert formatted date string back to $H date integer
 SET intDate = $ZDATEH("01/15/2025", 1)
 WRITE intDate, !                   // 67196 (days since 12/31/1840)

 SET intDate = $ZDATEH("2025-01-15", 3)
 WRITE intDate, !                   // 67196

 SET intDate = $ZDATEH("20250115", 8)
 WRITE intDate, !                   // 67196

$ZTIME: Formato de horas

 SET seconds = $PIECE($H, ",", 2)

 // Format 1: HH:MM:SS (24-hour)
 WRITE $ZTIME(seconds, 1), !       // 12:32:03

 // Format 2: HH:MM:SS AM/PM
 WRITE $ZTIME(seconds, 2), !       // 12:32:03 PM

 // Format 3: HH:MM:SS (same as 1)
 WRITE $ZTIME(seconds, 3), !       // 12:32:03

 // Just hours and minutes
 WRITE $ZTIME(seconds, 1, 2), !    // 12:32 (precision=2)

$ZTIMEH: Análisis de cadenas de hora

 // Convert time string to seconds since midnight
 SET secs = $ZTIMEH("14:30:00")
 WRITE secs, !                      // 52200

 SET secs = $ZTIMEH("2:30 PM", 2)
 WRITE secs, !                      // 52200

$NOW() y $ZTIMESTAMP

 // $NOW() returns local timestamp with fractional seconds
 WRITE $NOW(), !
 // Example: 67551,45123.456789

 // $ZTIMESTAMP returns UTC with fractional seconds
 WRITE $ZTIMESTAMP, !
 // Example: 67551,63123.456789 (UTC, may differ from local)
 // $ZTS is the shorthand
 WRITE $ZTS, !

4. Aritmética de fechas

Puntos Clave

  • Sumar días: Simplemente sume un entero al valor de fecha $H
  • Diferencias de fechas: Reste dos valores de fecha $H para obtener los días entre ellas
  • Aritmética de tiempo: Sume/reste segundos del valor de tiempo $H (manejar desbordamiento de día)
  • $SYSTEM.SQL.DATEDIFF(): Calcula diferencias en varias unidades (día, mes, año, hora, etc.)
  • $SYSTEM.SQL.DATEADD(): Agrega intervalos a fechas
  • Combinar fecha y hora: Recuerde que $H tiene dos piezas -- modifique cada una independientemente

Notas Detalladas

Descripción general

Dado que $HOROLOG representa fechas como conteos enteros de días y horas como enteros de segundos, la aritmética de fechas es sencilla: sumar o restar enteros. Para cálculos más complejos (meses, años), use las funciones de fecha $SYSTEM.SQL.

Aritmética simple de fechas

 SET today = +$H    // + extracts just the date part (first piece)

 // Tomorrow
 SET tomorrow = today + 1
 WRITE "Tomorrow: ", $ZDATE(tomorrow, 3), !

 // 30 days from now
 SET future = today + 30
 WRITE "30 days later: ", $ZDATE(future, 3), !

 // 7 days ago
 SET lastWeek = today - 7
 WRITE "Last week: ", $ZDATE(lastWeek, 3), !

Diferencias de fechas

 // Days between two dates
 SET date1 = $ZDATEH("2025-01-01", 3)
 SET date2 = $ZDATEH("2025-03-15", 3)
 SET diff = date2 - date1
 WRITE "Days between: ", diff, !    // 73

 // Days until a future event
 SET eventDate = $ZDATEH("2025-12-25", 3)
 SET today = +$H
 SET daysUntil = eventDate - today
 WRITE "Days until Christmas: ", daysUntil, !

Aritmética de tiempo

 SET now = $PIECE($H, ",", 2)

 // 2 hours from now
 SET later = now + (2 * 3600)
 // Handle overflow past midnight (86400 seconds per day)
 IF later >= 86400 {
     SET later = later - 86400
     // Also increment the date
 }
 WRITE "2 hours later: ", $ZTIME(later, 1), !

 // Minutes between two times
 SET time1 = $ZTIMEH("09:00:00")
 SET time2 = $ZTIMEH("17:30:00")
 SET minutes = (time2 - time1) \ 60
 WRITE "Minutes worked: ", minutes, !    // 510
 WRITE "Hours worked: ", minutes / 60, ! // 8.5

$SYSTEM.SQL.DATEDIFF y $SYSTEM.SQL.DATEADD

 // DATEDIFF: calculate difference in various units
 SET date1 = "2025-01-01"
 SET date2 = "2025-06-15"

 // Difference in days
 SET days = $SYSTEM.SQL.DATEDIFF("dd", date1, date2)
 WRITE "Days: ", days, !

 // Difference in months
 SET months = $SYSTEM.SQL.DATEDIFF("mm", date1, date2)
 WRITE "Months: ", months, !

 // Difference in years
 SET years = $SYSTEM.SQL.DATEDIFF("yy", "2000-01-01", "2025-06-15")
 WRITE "Years: ", years, !

 // DATEADD: add intervals to a date
 // Add 3 months to a date
 SET newDate = $SYSTEM.SQL.DATEADD("mm", 3, "2025-01-15")
 WRITE "3 months later: ", newDate, !    // 2025-04-15

 // Add 1 year
 SET nextYear = $SYSTEM.SQL.DATEADD("yy", 1, "2025-03-01")
 WRITE "Next year: ", nextYear, !        // 2026-03-01

 // Subtract 90 days
 SET past = $SYSTEM.SQL.DATEADD("dd", -90, "2025-06-15")
 WRITE "90 days ago: ", past, !

Combinación de fecha y hora

 // Build a full $H value from date and time
 SET dateH = $ZDATEH("2025-06-15", 3)
 SET timeH = $ZTIMEH("14:30:00")
 SET fullH = dateH _ "," _ timeH
 WRITE "Full $H: ", fullH, !

 // Calculate elapsed time between two $H timestamps
 SET start = "67196,32400"   // some date, 09:00:00
 SET end = "67197,7200"      // next day, 02:00:00

 SET startSec = ($P(start, ",", 1) * 86400) + $P(start, ",", 2)
 SET endSec = ($P(end, ",", 1) * 86400) + $P(end, ",", 2)
 SET elapsed = endSec - startSec
 WRITE "Elapsed seconds: ", elapsed, !
 WRITE "Elapsed hours: ", elapsed / 3600, !

Resumen de Preparación para el Examen

Conceptos críticos a dominar:

  1. Evaluación DE IZQUIERDA A DERECHA: Sin precedencia de operadores -- 2 + 3 * 4 = 20, no 14. Use siempre paréntesis
  2. División entera (\\): Trunca hacia cero, diferente del módulo (#)
  3. Formato $HOROLOG: días,segundos -- días desde el 31/12/1840, segundos desde medianoche
  4. Códigos de formato $ZDATE: Conocer al menos los formatos 1 (EE.UU.), 3 (ISO) y 8 (compacto)
  5. $ZDATEH: Inverso de $ZDATE -- convierte cadena formateada de vuelta a fecha interna
  6. Aritmética de fechas: Sumar/restar enteros para cálculos de días
  7. Aritmética de tiempo: Trabajar en segundos, manejar el límite de 86400 segundos por día
  8. $SYSTEM.SQL.DATEDIFF/DATEADD: Para cálculos de meses/años que la aritmética simple no puede manejar
  9. Operador NOT: Apóstrofo (') no signo de exclamación
  10. Cortocircuito: && y || hacen cortocircuito; & y operadores simples no

Escenarios comunes de examen:

  • Evaluar expresiones aritméticas con reglas de izquierda a derecha (preguntas trampa)
  • Convertir entre $HOROLOG y cadenas de fecha formateadas
  • Calcular el número de días entre dos fechas
  • Formatear fechas en diferentes formatos regionales usando $ZDATE
  • Determinar la salida de expresiones sin paréntesis
  • Usar $SYSTEM.SQL.DATEDIFF para diferencias de meses/años
  • Trabajar con $ZTIMESTAMP para marcas de tiempo UTC

Recomendaciones de práctica:

  • Escribir expresiones aritméticas y predecir resultados con evaluación de izquierda a derecha
  • Agregar paréntesis a expresiones y verificar el comportamiento modificado
  • Convertir fechas entre $HOROLOG y varias cadenas formateadas
  • Calcular diferencias de fechas y fechas futuras/pasadas
  • Usar $SYSTEM.SQL.DATEDIFF y $SYSTEM.SQL.DATEADD con diferentes unidades
  • Experimentar con $NOW() y $ZTIMESTAMP para temporización de precisión
  • Practicar con el operador NOT (') y comparaciones negadas ('=, '<, '>)

Report an Issue