domingo, 20 de octubre de 2013

Programación Java Calendario Gregoriano


INTRODUCCIÓN

Los calendarios informáticos actualmente son de mucho en las aplicaciones informáticas por uso amigable para seleccionar en forma interactiva fechas para asignar a campos de datos que estén relacionados con fechas en el calendario gregoriano. Este programa le permite al usuario seleccionar fechas (dd/mm/aaaa) desde el año 1583, año en que se inicio con este calendario. El nombre de calendario gregoriano se debe porque fue el Papa Gregorio XIII lo adoptó a partir de octubre de 1582 para corregir las imprecisiones con relación a las fiestas religiosas. El calendario gregoriano es usado internacionalmente en la actualidad para la programación de la medida del tiempo y más específicamente en el mundo occidental. Este programa en lenguaje java se construye sobre dos clases, llamadas Fecha y Calendario. La clase Fecha maneja todo lo relacionado con el manejo la programación de los cálculos del año, mes y día para las fechas desde el año 1583. La clase Calendario maneja todo lo relacionado con la vista del calendario tal como el que se muestra en la ilustración 1. La clase Calendario es una subclase de la clase JDialog del paquete javax.swing. Esta clase le permite al usuario interactuar con los programas para la selección de una fecha determinada la cual se puede buscar por años en forma ascendente o descendente y dentro de cada año se puede buscar también en ascendente o descendente por mes. Para seleccionar el día del mes se pulsa el botón al día requerido. Para cerrar el cuadro de diálogos del calendario se pulsa el botón de cierre. Una vez cerrado el calendario la aplicación que llamó este programa puede tomar los valores del año, mes y día seleccionado desde las variables públicas estáticas: Fecha.DIA, Fecha.MES y Fecha.AÑO.
Para el uso de la clase Calendario se hace mediante las siguientes sentencias de java: int x=100, y= 150; // Coordenada de posición del cuadro de diálogos del calendario Calendario
cal=new Calendario(x,y);
int año= Fecha.AÑO, mes=Fecha.MES, dia=Fecha.DIA;

CÓDIGO FUENTE JAVA DE LA CLASE FECHA

import java.util.Calendar;
public class Fecha {
public static int AÑO,MES,DIA;
private int aa,mm,dd;
Calendar calendario=Calendar.getInstance();
private static boolean esBisiesto(int aa){
return (aa%4==0 && aa%100==0)||(aa%400==0);
}
public static int getDiasMes(int aa,int mm){
int dias=31;
switch(mm){
case 4:case 6:case 9:case 11:dias=30;break;
case 2:if(esBisiesto(aa))dias=29;else dias=28;break;
}
return dias;
}
public Fecha(){
aa=calendario.get(Calendar.YEAR);
mm=calendario.get(Calendar.MONTH)+1;
dd=calendario.get(Calendar.DAY_OF_MONTH);
}
public Fecha(int aa,int mm,int dd){
try{
if(aa<1583)throw new Exception("...");
this.aa=aa;
if(mm<1||mm>12)throw new Exception("...");
this.mm=mm;
if(dd<1||dd>getDiasMes(aa,mm))throw new Exception("...");
this.dd=dd;
}catch(Exception e){
this.aa=calendario.get(Calendar.YEAR);
this.mm=calendario.get(Calendar.MONTH)+1;
this.dd=calendario.get(Calendar.DAY_OF_MONTH);
}
}
public int getAño() {
return aa;
}
public void setAño(int aa) {
// Precondición: aa>1582
this.aa=aa;
}
public int getMes() {
return mm;
}
public void setMes(int mm) {
// Precondición: mm>0 && mm<13
this.mm=mm;
}
public int getDia() {
return dd;
}
public void setDia(int dd) {
// Precondición: dd>0 && dd< getDiasMes(aa,mm)
this.dd=dd;
}
public int getDiaSemana(){
// d= [0= domingo, 1= lunes, ... 6= sabado]
int a,y,m,d;
a=(14-mm)/12;
y=aa-a;
m=mm+12*a-2;
d=(dd+y+y/4-y/100+y/400+(31*m)/12)%7;
return d;
}
public void incrementarAño(){
aa++;
mm=1;
dd=1;
}
public void decrementarAño(){
if(aa>1583){
aa--;
mm=1;
dd=1;
}
}
public void incrementarMes(){
if(mm==12){
mm=1;
aa++;
dd=1;
}else{
mm++;
dd=1;
}
}
public void decrementarMes(){
try{
if((aa==1583) && (mm==1)) throw new Exception("...");
if(mm==1){
mm=12;
aa--;
dd=1;
}else{
mm--;
dd=1;
}
}catch(Exception e){}
}
public String toStringFecha(){
return dd+"/"+mm+"/"+aa;
}
public int getDiasMes(){
int dias=31;
switch(mm){
case 4:case 6:case 9:case 11:dias=30;break;
case 2:if(esBisiesto(aa))dias=29;else dias=28;break;
}
return dias;
}
}

CÓDIGO FUENTE CLASE Calendario

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Calendario extends JDialog implements ActionListener {
private final int ANCHO=250,ALTO=183;
Color blanco=new Color(255,255,255);
Color azulMar=new Color(0,150,150);
Color amarillo=new Color(255,255,0);
Color rojoFestivo=new Color(240,0,0);
Color rojoCierre=new Color(150,0,0);
final String cruzCierre="\u2716";
final String puntaAtrazar="\u25C4";
final String puntaAdelantar="\u25BA";
int d=0,n=0;
Fecha fecha=new Fecha();
private JPanel panelTit,panelMes,panelSemana,panelDiasMes;
private JLabel etiqAño,etiqFecha,etiqMes;
private JButton btnCerrar,btnAtrasAño,btnAdelanteAño;
private JButton btnAtrasMes,btnAdelanteMes;
private JButton btnSemana[]=new JButton[7];
private JButton btnDias[]=new JButton[42];
private String diasSemana[]={"dom","lun","mar","mie","jue","vie","sab"};
private String meses[]={"enero","febrero","marzo","abril","mayo","junio",
"julio","agosto","septiembre","octubre","noviembre","diciembre"};
public Calendario(int x,int y){
this.setModal(true);
setSize(ANCHO,ALTO);
setUndecorated(true);
this.setLocation(x, y);
setLayout(null);
inicioComponentes();
setVisible(true);
}
private void inicioComponentes(){
panelTit=new JPanel();
panelTit.setBounds(0,0,250,20);
panelTit.setBackground(azulMar);
panelTit.setLayout(null);
btnCerrar=new JButton(cruzCierre);
btnCerrar.setBounds(220,3,25,15);
btnCerrar.setBorder(BorderFactory.createLineBorder(blanco));
btnCerrar.setBackground(rojoCierre);
btnCerrar.setForeground(blanco);
panelTit.add(btnCerrar);
btnAtrasAño=new JButton(puntaAtrazar);
btnAtrasAño.setBounds(3,3,25,15);
btnAtrasAño.setBackground(azulMar);
btnAtrasAño.setForeground(blanco);
btnAtrasAño.setBorder(BorderFactory.createEmptyBorder());
panelTit.add(btnAtrasAño);
btnAdelanteAño=new JButton(puntaAdelantar);
btnAdelanteAño.setBounds(105,3,25,15);
btnAdelanteAño.setBackground(azulMar);
btnAdelanteAño.setForeground(blanco);
btnAdelanteAño.setBorder(BorderFactory.createEmptyBorder());
panelTit.add(btnAdelanteAño);
etiqFecha=new JLabel(fecha.toStringFecha());
etiqFecha.setBounds(130,3,80,15);
etiqFecha.setBackground(azulMar);
etiqFecha.setForeground(blanco);
etiqFecha.setHorizontalAlignment(JLabel.CENTER);
panelTit.add(etiqFecha);
add(panelTit);
etiqAño=new JLabel(Integer.toString(fecha.getAño()));
etiqAño.setBounds(30,3,70,15);
etiqAño.setForeground(blanco);
etiqAño.setHorizontalAlignment(JLabel.CENTER);
panelTit.add(etiqAño);
btnCerrar.addActionListener(this);
panelMes=new JPanel();
panelMes.setBounds(0,21,250,20);
panelMes.setBackground(blanco);
panelMes.setLayout(null);
btnAtrasMes=new JButton(puntaAtrazar);
btnAtrasMes.setBounds(40,3,25,15);
btnAtrasMes.setBorder(BorderFactory.createEmptyBorder());
btnAtrasMes.setBackground(blanco);
btnAtrasMes.setForeground(azulMar);
panelMes.add(btnAtrasMes);
etiqMes=new JLabel(meses[fecha.getMes()-1]);
etiqMes.setBounds(70,3,110,15);
etiqMes.setForeground(azulMar);
etiqMes.setHorizontalAlignment(JLabel.CENTER);
panelMes.add(etiqMes);
btnAdelanteMes=new JButton(puntaAdelantar);
btnAdelanteMes.setBounds(185,3,25,15);
btnAdelanteMes.setBorder(BorderFactory.createEmptyBorder());
btnAdelanteMes.setBackground(blanco);
btnAdelanteMes.setForeground(azulMar);
panelMes.add(btnAdelanteMes);
add(panelMes);
panelSemana=new JPanel();
panelSemana.setBounds(0,42,250,20);
panelSemana.setBackground(blanco); panelSemana.setLayout(new GridLayout(0,7,0,2));
for(int i=0;i btnSemana[i]=new JButton(diasSemana[i]);
btnSemana[i].setBackground(azulMar);
btnSemana[i].setBorder(BorderFactory.createEtchedBorder());
if(i==0)btnSemana[i].setForeground(new Color(255,0,0));
else btnSemana[i].setForeground(new Color(255,255,255));
panelSemana.add(btnSemana[i]);
}
add(panelSemana);
panelDiasMes=new JPanel();
panelDiasMes.setBounds(0,63,250,120);
panelDiasMes.setBackground(blanco);
panelDiasMes.setLayout(new GridLayout(6,7,0,2));
add(panelDiasMes);
for(int i=0;i btnDias[i]=new JButton();
btnDias[i].setBackground(blanco);
btnDias[i].setBorder(BorderFactory.createEtchedBorder());
btnDias[i].addActionListener(this);
panelDiasMes.add(btnDias[i]);
}
establecerEncabezados();
establecerMes();
btnAtrasAño.addActionListener(this);
btnAdelanteAño.addActionListener(this);
btnAtrasMes.addActionListener(this);
btnAdelanteMes.addActionListener(this);
}
private void limpiarGridMes(){
for(int indDias=0;indDias btnDias[indDias].setBackground(blanco);
btnDias[indDias].setText(null);
btnDias[indDias].setEnabled(false);
}
}
public void actionPerformed (ActionEvent ev){
if(ev.getSource()==btnCerrar){
Fecha.AÑO=fecha.getAño();
Fecha.MES=fecha.getMes();
Fecha.DIA=fecha.getDia();
this.dispose();
}else{
int diaTemp=fecha.getDia();
fecha.setDia(1);
d=fecha.getDiaSemana();
n=fecha.getDiasMes();
fecha.setDia(diaTemp);
for(int dia=d;dia if(btnDias[dia]==ev.getSource()){
btnDias[d+diaTemp-1].setBackground(blanco);
fecha.setDia(Integer.parseInt(btnDias[dia].getText()));
etiqFecha.setText(fecha.toStringFecha());
btnDias[dia].setBackground(amarillo);
}
}
}
if(ev.getSource()==btnAtrasAño){
atrazarAño();
}else if(ev.getSource()==btnAdelanteAño){
adelantarAño();
}else if(ev.getSource()==btnAtrasMes){
atrazarMes();
}else if(ev.getSource()==btnAdelanteMes){
adelantarMes();
}
}
private void establecerEncabezados(){
etiqAño.setText(String.valueOf(fecha.getAño()));
etiqFecha.setText(fecha.toStringFecha());
etiqMes.setText(meses[fecha.getMes()-1]);
}
private void atrazarAño(){
fecha.decrementarAño();
establecerEncabezados();
limpiarGridMes();
establecerMes();
}
private void adelantarAño(){
fecha.incrementarAño();
establecerEncabezados();
limpiarGridMes();
establecerMes();
}
private void atrazarMes(){
fecha.decrementarMes();
establecerEncabezados();
limpiarGridMes();
establecerMes();
}
private void adelantarMes(){
fecha.incrementarMes();
establecerEncabezados();
limpiarGridMes();
establecerMes();
}
private void establecerMes(){
int nDias=fecha.getDiasMes();
int diaActual =fecha.getDia();
fecha.setDia(1);
int dia1Semana=fecha.getDiaSemana();
fecha.setDia(diaActual);
for(int i=dia1Semana,dia=1;i btnDias[i].setEnabled(true);
btnDias[i].setText(String.valueOf(dia));
if(i%7==0)btnDias[i].setForeground(new Color(255,0,0));
if(dia==diaActual)btnDias[i].setBackground(amarillo);
}
}
}

ALGORITMOS CLAVES

ALGORITMO ZELLER
El algoritmo clave que se utilizó para hallar el día de la semana en que cae o cayó una fecha determinada es el algoritmo de secuencias de Zeller. Dada una fecha cualquiera dd/mm/aaaa el día de la semana es d: <0= domingo, 1= lunes, 2=martes, 3= miércoles, 4= jueves, 5= viernes, 6= sábado>, el valor de d se calcula según el siguiente algoritmo:
ALGORITMO Zeller :
a,y,m,d : int
a=(14-mm)/12;
y=aa-a;
m=mm+12*a-2;
d=(dd+y+y/4-y/100+y/400+(31*m)/12)%7;
return d;
FIN ALGORITMO Zeller
Este algoritmo se utilizó en el método getDiaSemana() de la clase Fecha.
ALGORITMO ESBISIESTO
ALGORITMO esBisiesto:
A: año es divisible por 4
B: año es divisible por 100
C: año es divisible por 400
Un año aaaa es bisiesto si: A es cierto y B es cierto o C es cierto
FIN ALGORITMO esBisiesto