IBM DFSORT, 11 3 linhas de 71, 72 ou 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)
As duas respostas com formato de saída colunar resistiram ao teste do tempo. Isso me dá um "loop", mais ou menos, em que em OUTFIL REPEAT = copia o registro atual várias vezes.
Técnica diferente para chegar ao valor, que parece mais longo, mas é mais curto, pois não consigo encontrar uma maneira incondicional de lidar com o 12º registro no ano seguinte, e torná-lo condicional significa incluir IFTHEN=(WHEN=
duas vezes e outras coisas. O ganho nas oscilações (primeiro do mês é a maneira mais simples de fazê-lo) perde muito nas rotatórias (requisitos específicos de sintaxe).
Isso usa uma função embutida (todas as funções no DFSORT são embutidas) para encontrar o último dia do mês. Em seguida, adiciona um dia (função) para chegar ao primeiro mês seguinte e usa a função PREVDSUN para obter o domingo anterior (que sempre será o último domingo do mês anterior, como antes).
Ao transformar o ano (entrada) em uma data válida, um número de seqüência de dois dígitos é usado para o mês, e esse valor também é copiado para o dia, pois o ponto de partida não importa enquanto válido, pois estamos após o último dia do mês inicialmente: 5,2
é menor que C'01'
.
Aqui está o detalhe:
OPTION COPY - copia o arquivo de entrada para a saída
OUTFIL - para permitir que vários arquivos de saída, com seleção e formatação diferentes, produzam relatórios formatados. Utilizado de preferência ao mais curto INREC
devido ao uso de REPEAT=
.
REPEAT = 12 - produza 12 cópias de cada registro. Neste exemplo, pode haver apenas um registro de entrada (diferente da versão anterior) devido ao SEQNUM.
5: - comece na coluna 5 do registro.
SEQNUM, 2, ZD - número de sequência, o padrão é iniciar com um, dois dígitos, "decimal zonado" (para não assinado, qual será o mesmo que o caractere).
1,8 - copie os bytes 1 do comprimento 8 para o local atual (9). Isso ocorre porque o Y4T precisa ver esse 8, caso contrário, um formato de data diferente será usado.
Y4T - data no formato ccyymmdd (devido aos 8 imediatamente à frente).
ÚLTIMO DIA - Último dia do mês (também possível da semana, trimestre e ano).
TOJUL = - gera conversão de data para funções de data (TOJUL é um caractere menor que TOGREG)
9,7 - agora que tem 7 anos, o Y4T será CCYYDDD.
ADDDAYS - adiciona vários dias, ajustando-se automaticamente se o mês / ano seguinte (também pode ser ADDMONS and ADDYEARS)
PREVDSUN - a data juliana chega, domingo anterior está localizado, TOGREG para obter o formato de saída correto, com o separador "-" (pode ser o que você quiser como separador)
12X - espaços em branco para esclarecer a bagunça que nos permitiu fazê-lo de maneira tão curta
O resultado acima, para 2014, é:
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
É necessário algo para dizer ao SORT o que fazer. Não há padrão. OPTION COPY
é o mais curto, SORT FIELDS=COPY
é equivalente, mas mais longo.
O trabalho em si realizado desta vez OUTFIL
(para permitir o uso de REPEAT). O código de trabalho é sem dúvida qualquer um dos 160 (2 * 80), 144 (2 * 72), 140 (72 + 69) ou 138 (70 + 68) (excluindo os espaços em branco à esquerda, continuação forçada e espaços em branco à direita).
Dado que o receptor precisaria saber o que está fazendo, acho que posso dizer que o código DFSORT para listar o último domingo de cada mês para qualquer ano de 1900 (será executado a partir do ano 0001, mas estou evitando a pesquisa como bem) até 9999 (embora o DFSORT suporte anos até 9999, a solução anterior não funcionaria no ano 9999 desde a 12ª data do ano seguinte) pode ser tweetada.
Por que o código é tão longo, se existem funções embutidas especialmente adequadas?
As definições de campo são efêmeras. Um campo é definido apenas como um local específico nos dados (que é um registro) para uso imediato. Em outras palavras, os campos não são definidos como tal, mas são definidos para cada uso e apenas para uso. As funções de data precisam saber quais (de muitos) formatos de data são usados para a fonte e a saída deve estar em um formato de data, para que seja necessário especificar.
Agora que temos um encontro juliano ... TBC?
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)
Precisa de algum JCL
//LASTSUNG EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTOUT DD SYSOUT=*
//SYSIN DD *
E um arquivo de entrada (outra linha da JCL e três itens de dados em sequência):
//SORTIN DD *
2014
1900
2000
Produz:
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
Na verdade, funcionará até o ano 9999.
DFSORT é o produto de classificação de mainframe da IBM. Os dados podem ser manipulados, mas como a classificação é a chave e as classificações geralmente são grandes e de longa execução, os cartões de controle DFSORT não têm construções em loop, portanto, não podemos colocar um SORT em um loop. Torna as coisas um pouco complicadas para tarefas como o golfe.
Por que postar a resposta, é porque o DFSORT tem uma PREVDday
função. Então, no último domingo de um mês é fácil. É o domingo anterior (PREVDSUN) para o primeiro dia do mês seguinte.
Também foi divertido fazer isso dentro de um "operando" (OVERLAY), um pouco como fazer tudo dentro sprintf
ou similar.
Aqui é ungolfed:
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)
Embora não seja um abuso, não seria comum tentar colocar tudo isso em um OVERLAY, e há algumas coisas aparentemente desnecessárias necessárias para permitir que tudo entre em um OVERLAY. Há espaço para jogar golfe, mas, como isso removeria apenas uma linha, no máximo, não sou tentado.
O INREC é processado para cada registro.
OVERLAY permite alterar o conteúdo de um registro existente. Se o registro for estendido além do seu comprimento no processo, isso não será um problema.
1,4 é o ano que se aproxima. Ele tem um literal de 0201 anexado e, em seguida, os 1,8s sucessivos o repetem 11 vezes para dar um longo mandril de 96 bytes,
O 12º ano no registro atual estendido recebe 1 adicionado a ele e seu mês é igual a 1 (janeiro).
Os 10 meses restantes são alterados para 3 a 11.
Existem 12, na ordem inversa (devido a OVERLAY) deste tipo de coisa:
127:X,89,8,Y4T,PREVDSUN,TOGREG=Y4T(-),
O n: é um número de coluna no registro. O X insere um espaço em branco. 89,8 pega os dados dessa coluna / comprimento, o Y4T os trata como uma data CCYYMMDD, PREVDSUM trabalha no domingo anterior, TOGREG = Y4T (-) o exibe como uma data gregoriana CCYY-MM-DD.
Como você recebe lixo se a origem e o destino de uma parte específica de um OVERLAY se sobrepõem destrutivamente, o final 11:X,18,120,6X)
reorganiza e mascara um pouco de confusão.
Os manuais e os documentos podem ser encontrados em: http://www-01.ibm.com/support/docview.wss?uid=isg3T7000080 e inclui o Guia de programação de aplicativos DFSORT da página 900+.
Como em todos os produtos IBM, todos os manuais estão disponíveis gratuitamente (exceto uma quantidade excruciante pequena de itens muito caros que apenas um número muito pequeno de pessoas no mundo fingiria entender).
Todos os cartões de controle DFSORT devem começar com um espaço em branco. A coluna 72 é usada apenas para continuação (qualquer não em branco serve, mas * é convencional). A coluna 72 é seguida por uma área de número de sequência que é ignorada, tornando cada registro 80 bytes.
Talvez mais algumas soluções por vir.