IBM DFSORT, 11 3 líneas de 71, 72 u 80 caracteres
OPTION COPY
OUTFIL REPEAT=12,OVERLAY=(5:SEQNUM,2,ZD,5,2,1,8,Y4T,LASTDAYM,TOJUL=Y4T*
,9,7,Y4T,ADDDAYS,+1,TOJUL=Y4T,1:16,7,Y4T,PREVDSUN,TOGREG=Y4T(-),12X)
Las dos respuestas con formato de salida en columna han resistido la prueba del tiempo. Eso me da un "bucle", más o menos, en que en OUTFIL REPEAT = copia el registro actual que muchas veces.
Una técnica diferente para llegar al valor, que parece más larga pero más corta, ya que no puedo encontrar ninguna forma incondicional de lidiar con el duodécimo registro en el año siguiente, y hacerlo condicional significa que incluye IFTHEN=(WHEN=
, dos veces y algunas otras cosas. Gane en los cambios (el primer mes es la forma más sencilla de hacerlo) pierda mucho en las rotondas (requisitos de sintaxis particulares).
Esto utiliza una función incorporada (todas las funciones en DFSORT están incorporadas) para encontrar el último día del mes. Luego agrega un día (función) para llegar al primero del mes siguiente y usa la función PREVDSUN para obtener el domingo anterior (que siempre será el último domingo del mes anterior, como antes).
Al convertir el año (entrada) en una fecha válida, se usa un número de secuencia de dos dígitos para el mes, y ese valor también se copia para el día, ya que el punto de partida no importa mientras sea válido, ya que somos después del último día del mes inicialmente: 5,2
es más corto queC'01'
.
Aquí está el detalle:
OPTION COPY - copia el archivo de entrada a la salida
OUTFIL: para permitir múltiples archivos de salida, con diferente selección y formato, producir informes formateados. Se usa con preferencia al más corto INREC
debido al uso de REPEAT=
.
REPETIR = 12 - produce 12 copias de cada registro. En este ejemplo, solo puede haber un registro de entrada (a diferencia de la versión anterior) debido a SEQNUM.
5: comienza en la columna 5 del registro.
SEQNUM, 2, ZD: número de secuencia, por defecto comienza en uno, dos dígitos, "decimal con zona" (para sin signo, que serán, igual que el carácter).
1,8 - copie los bytes 1 para la longitud 8 en la ubicación actual (9). Esto se debe a que el Y4T necesita ver ese 8, de lo contrario se usará un formato de fecha diferente.
Y4T: fecha de formato ccyymmdd (debido a los 8 que se encuentran inmediatamente delante).
LASTDAYM - Último día del mes (también posible de semana, trimestre y año).
TOJUL = - conversión de fecha de salida para funciones de fecha (TOJUL es un carácter menos que TOGREG)
9,7 - ahora que tiene 7 largos, Y4T será CCYYDDD.
ADDDAYS: agrega una cantidad de días, ajustándose automáticamente si entra en el siguiente mes / año (también podría ser ADDMONS y ADDYEARS)
PREVDSUN: aparece la fecha juliana, se ubica el domingo anterior, TOGREG para obtener el formato de salida correcto, con el separador "-" (podría ser cualquier cosa que desee como separador)
12X: espacios en blanco para aclarar el desorden que nos ha permitido hacerlo de una manera tan corta
El resultado de lo anterior, para 2014, es:
2014-01-26
2014-02-23
2014-03-30
2014-04-27
2014-05-25
2014-06-29
2014-07-27
2014-08-31
2014-09-28
2014-10-26
2014-11-23
2014-12-28
Se requiere algo para decirle al SORT qué hacer. No hay defecto. OPTION COPY
es el más corto, SORT FIELDS=COPY
es equivalente pero más largo.
El trabajo en sí lo hizo esta vez OUTFIL
(para permitir el uso de REPEAT). Podría decirse que el código de trabajo es cualquiera de 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) o 138 (70 + 68) (excluyendo los espacios en blanco iniciales, la continuación forzada y los espacios en blanco finales).
Dado que el receptor tendría que saber lo que está haciendo, creo que puedo decir que el código DFSORT para enumerar el último domingo de cada mes para cualquier año desde 1900 (se ejecutará desde el año 0001, pero estoy evitando la investigación como bien) hasta 9999 (aunque DFSORT admite años hasta 9999, la solución anterior no funcionaría en el año 9999 ya que la duodécima fecha entra en el año siguiente) se puede tuitear.
¿Por qué el código es tan largo si hay funciones incorporadas especialmente adecuadas?
Las definiciones de campo son efímeras. Un campo solo se define como una ubicación particular dentro de los datos (que es un registro) para su uso inmediato. En otras palabras, los campos no se definen como tales, sino que se definen para cada uso y solo para su uso. Las funciones de fecha necesitan saber qué (de muchos) formatos de fecha se utilizan para la fuente, y la salida debe estar en un formato de fecha, por lo que debe especificarse.
Ahora que tenemos una cita juliana ... ¿Por confirmar?
OPTION COPY
INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,8*
,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4,14:C'3',22:C'4',30:C'5',38:C'6',*
46:C'7',54:C'8',62:C'9',69:C'10',77:C'11',85:C'12',127:X,89,8,Y4T,PREV*
DSUN,TOGREG=Y4T(-),116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-),105:X,73,8,Y4*
T,PREVDSUN,TOGREG=Y4T(-),94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-),83:X,57,*
8,Y4T,PREVDSUN,TOGREG=Y4T(-),72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-),61:X*
,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-),50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-),*
39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-),28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T*
(-),17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-),1:1,8,Y4T,PREVDSUN,TOGREG=Y4T*
(-),11:X,18,120,6X)
Necesita algo JCL
//LASTSUNG EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTOUT DD SYSOUT=*
//SYSIN DD *
Y un archivo de entrada (otra línea de JCL y tres elementos de datos integrados):
//SORTIN DD *
2014
1900
2000
Produce:
2014-01-26 2014-02-23 2014-03-30 2014-04-27 2014-05-25 2014-06-29 2014-07-27 2014-08-31 2014-09-28 2014-10-26 2014-11-30 2014-12-28
1900-01-28 1900-02-25 1900-03-25 1900-04-29 1900-05-27 1900-06-24 1900-07-29 1900-08-26 1900-09-30 1900-10-28 1900-11-25 1900-12-30
2000-01-30 2000-02-27 2000-03-26 2000-04-30 2000-05-28 2000-06-25 2000-07-30 2000-08-27 2000-09-24 2000-10-29 2000-11-26 2000-12-31
Realmente funcionará hasta el año 9999.
DFSORT es el producto de clasificación de mainframe de IBM. Los datos se pueden manipular, pero dado que la clasificación es clave y los tipos son a menudo grandes y de larga duración, las tarjetas de control DFSORT no tienen construcciones de bucle, por lo que no podemos poner un SORT en un bucle. Hace las cosas un poco largas para tareas como Golf.
Por qué publicar la respuesta, es porque DFSORT tiene una PREVDday
función. Así que el último domingo de un mes es fácil. Es el domingo anterior (PREVDSUN) al primer día del mes siguiente.
También fue divertido hacerlo dentro de un "operando" (OVERLAY), un poco como hacerlo todo dentro sprintf
o similar.
Aquí no tiene golf:
OPTION COPY
INREC OVERLAY=(1,4,C'0201',1,8,1,8,1,8,1,8,1,8,1,8,
1,8,1,8,1,8,1,8,
1,8,94:C'1',89:1,4,ZD,ADD,+1,ZD,LENGTH=4,
14:C'3',22:C'4',30:C'5',38:C'6',46:C'7',54:C'8',
62:C'9',69:C'10',77:C'11',85:C'12',
127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
116:X,81,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
105:X,73,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
94:X,65,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
83:X,57,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
72:X,49,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
61:X,41,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
50:X,33,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
39:X,25,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
28:X,17,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
17:X,09,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
1:1,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
11:X,18,120,6X)
Si bien no es un abuso, no sería habitual tratar de agrupar todo esto en un REVESTIMIENTO, y hay algunas cosas aparentemente innecesarias que se necesitan para permitir que todo entre en un REVESTIMIENTO. Hay espacio para jugar al golf, pero como solo eliminaría una línea como máximo, no estoy tentado.
El INREC se procesa para cada registro.
OVERLAY permite cambiar el contenido de un registro existente. Si el registro se extiende más allá de su longitud en el proceso, eso no es un problema.
1,4 es el año entrante. Tiene un literal de 0201 adjunto, y luego los sucesivos 1,8s lo repiten 11 veces para dar una tirada larga de 96 bytes,
El duodécimo año en el registro actual extendido obtiene 1 agregado y su mes se convierte en 1 (enero).
Los 10 meses restantes se cambian de 3 a 11.
Luego hay 12, en orden inverso (debido a la REVESTIMIENTO) de este tipo de cosas:
127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
El n: es un número de columna en el registro. La X inserta un espacio en blanco. 89,8 toma los datos de esa columna / longitud, Y4T los trata como una fecha CCYYMMDD, PREVDSUM funciona el domingo anterior, TOGREG = Y4T (-) los emite como una fecha gregoriana CCYY-MM-DD.
Debido a que obtienes basura si la fuente y el objetivo de una parte particular de un OVERLAY se superponen destructivamente, el 11:X,18,120,6X)
reordenamiento final y enmascara un poco de desorden.
Los manuales y documentos se pueden encontrar en: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 , e incluye la Guía de programación de aplicaciones DFSORT de más de 900 páginas.
Al igual que con todos los productos de IBM, todos los manuales están disponibles de forma gratuita (excepto una cantidad insoportablemente pequeña de costosos que solo un número muy pequeño de personas en el mundo fingiría entender).
Todas las tarjetas de control DFSORT deben comenzar con un espacio en blanco. La columna 72 solo se usa para la continuación (cualquier no en blanco servirá, pero * es convencional). La columna 72 es seguida por un área de número de secuencia que se ignora, haciendo que cada registro sea de 80 bytes.
Otro par de soluciones por venir, tal vez.