[Métodos] Copiar y pegar desde el portapapeles en java

Para poder copiar y pegar desde el portapapeles del sistema con java vamos a hacer uso de de las siguientes clases e interfaz, por lo cual va a ser necesario importarlas:





Copiar



Procedimiento


Lo primero que debemos hacer para copiar del portapapeles es acceder al método de clase de toolkit getDefaultToolkit:

Luego debemos llamar a otro método de esta clase, getSystemClipboard:


Ahora usaremos un método de la clase ClipBoard que devuelve una instancia de la clase Transferable:


Proximo paso es usar el método de la interfaz transferable, getTransferData:


Por ultimo, como me resulta mas facil, casteo el Objet a String




Toolkit tool = Toolkit.getDefaultToolkit();
Clipboard clip = tool.getSystemClipboard();
Transferable trans = clip.getContents(null);
Object objeto = trans.getTransferData(DataFlavor.stringFlavor);
String str = (String) objeto;



De igual manera podemos ahorranos unos pasos, pero para mi es menos claro como se suceden las cosas realmente, en la practica no importará como se llegue al resultado.

Pegar



Procedimiento


Primer paso (no tan obvio) debemos tener nuestro String o cualquiera objeto que podamos llevarlo a string para pasarselo por parámetro del constructor del StringSelection

Ahora creamos el objeto de la clase StringSelection desde su único constructor:
Lo siguiente, es repetir los pasos:
  • crear el kit de herramientas por defecto del sistemas
  • este objeto llamará al método getSystemClipBoard() y devolvera un clipBoard
  • este nuevo objeto quien llamará al método set para modificar el portapales:
Será el objeto de la clase ClipBoard que lamé a su método sin retorno pasando el StringSelection como parametro:
  • public void setContents(Transferable contents, ClipboardOwner owner)
    • Establece el contenido actual del portapapeles al objeto transferable especificado y registra el dueño del portapapeles como el propietario de los nuevos contenidos.
    • Parámetros:
    • Transferable contents - El contenido del objeto transferibles que representa el contenido del portapapeles.
      ClipBoardOwner owner - el objeto que posee el contenido del portapapeles, o null si no es nadie.




String aPegar = "Este es el texto a pegar en el portapapeles";
StringSelection ss = new StringSelection(aPegar);
Toolkit tool = Toolkit.getDefaultToolkit();
Clipboard clip = tool.getSystemClipboard();
clip.setContents(ss, null);




public void pegarPortapapeles(String pegado){
    StringSelection ss = new StringSelection(pegado);
    Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);  
}
public String copiarPortapapeles() throws UnsupportedFlavorException, IOException {
    Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
    String copiado = (String) t.getTransferData(DataFlavor.stringFlavor);
    return copiado;
}

[Métodos] Expresión Regular


RegEx


RegEx ('Regular Expression' en inglés) según la Wikipedia es una secuencia de caracteres que forma un patrón de búsqueda, principalmente utilizada para la búsqueda de patrones de cadenas de caracteres u operaciones de sustituciones.

Ademas pone un lindo ejemplo:


l grupo formado por las cadenas Handel, Händel y Haendel se describe con el patrón "H(a|ä|ae)ndel"

La verdad yo no entendi mucho, y agrega:


n informática, las expresiones regulares proveen una manera muy flexible de buscar o reconocer cadenas de texto.




Básicamente podemos decir que una expresión regular es un codigo raro como:

  ([a-zA-Z]\w*?)

Pero nos permite a través de esos caracteres con operadores, palabras, o secuencia de caracteres que deseamos encontrar si no conocemos bien con exactitud lo que estamos buscando dentro de una cadena de texto.

En java usamos las clases del paquete java.util.regex:




Una manera de invocar expresiones regulares es:

  String cadena = "aaaaab";
  Pattern p = Pattern.compile("a*b");
  Matcher m = p.matcher(cadena);
  boolean b = m.matches();

El booleano deberia devolver true ya que buscamos:

  • a* que contega la letra 'a' un número indeterminado de veces con el operador '*'
  • b seguido de una letra 'b'
Dicha expresión regular se encuentra dentro de la cadena de texto que buscamos y por lo tanto la condicion termina siendo verdadera.
Otra manera de invocar una expresión regular en una sola línea es:

  boolean b = Pattern.matches(String regex, CharSequence input);

De la misma manera que lo hace la clase String :
  public boolean matches(String arg0) {
         return Pattern.matches(arg0, this);
  }

Pasando como parámetros la expresión regular como un String y nuestro texto como una clase que implemente la interfaz CharSequence, las cuales son:



Resumen de las construcciones de expresiones regulares


Patrón Igualación a Descripción
x el caracter x Una letra cualquiera se iguala a la misma.
[abc] letra a ó b ó c cual quier palabra que contenga alguna de las letras dentro del corchete.
[^abc] cualquier caracter excepto la 'a' 'b' 'c' el operador ^ es de negación, aunque la palabra contenga la 'a', matcheara con las otras letras.
[a-zA-Z] cualquier letra desde la 'a' hasta la 'z' rango de valores desde la primera letra a la segunda en minúsculas y mayúsculas.
[a-d[m-p]] cualquier letra desde la 'a' hasta la 'd' y también desde la 'm' a la 'p' unión de rangos de valores distintos.
[a-z&&[def]] cualquier letra desde la 'a' hasta la 'z' que sean iguales a 'd','e' y 'f' intersección de rangos de letras.
[a-z&&[^bc]] cualquier letra desde la 'a' hasta la 'z' excepto las letras 'b' y 'c' Substracción de rango de letras.
[a-z&&[^m-p]] cualquier letra de la 'a' a la 'z' excepto el rango de de 'm' a 'p' idem anterior pero con un rango de letras.
. Cualquier caracter (no solo letras) _Comodin para todos los caracteres.
\d un digito de 0 a 9 rango numerico decimal.
\D un no digito de 0 a 9 (letras y caracteres) negación de un rango númerico de 0 a 9.
\s un espacio en blanco similar a los tipos: [ \t\n\x0B\f\r]
\S un NO espacio en blanco la mayúscula es negación.
\w similar a [a-zA-Z_0-9] un caracter alfanúmerico
\W un NO caracter alfanúmerico negacion de [^/w]
^ El principio de una linea operador que indica agrega información al patrón
$ final de la línea operador que indica agrega información al patrón
\b limite de una palabra operador que indica agrega información al patrón
\B un NO limite de una palabra operador que indica agrega información al patrón
\A el principio de un input operador que indica agrega información al patrón
\G el final del macheo anterior operador que indica agrega información al patrón
\Z el final de una linea (\n \r\n \r \u0085 \u2028 \u2029) operador que indica agrega información al patrón
\z el final de un input operador que indica agrega información al patrón
X? X, al menos una vez o ninguna vez ? cuantificar una o ninguna
X* x cero veces o más * cuantificador cero o más
X+ X al menos una vez o más veces + cuantificador una o más
X{n} X 'n' veces exactamente el número de n veces
X{n,} X al menos el número de n veces cuantificador n veces o más
X{n,m} X n veces y no mas de m veces cuantificador de rango entre n y m veces (n<m)




Ya una vez empezando a entender como funcionan los patrones, solo queda jugar con los métodos de la clase Matcher


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public boolean expReg(String patron, String texto){
    Pattern p = Pattern.compile(patron);
    Matcher m = p.matcher(texto);
    return m.matches();
}

public static String expReg(String patron, String texto){
    Pattern p = Pattern.compile(patron);
    Matcher m = p.matcher(texto);
    if(m.matches())
    return m.replaceAll("EEE");
    else
    return "El patrón no se encontraba en el texto";
}






ReGex Java Online


Otra manera de aprender y encontrar patrones de expresión regular es con los regex online para java.

Entre muchos otros, y solo online sino tambien como plugins de IDEs o version desktop, pero por ejemplo:



Regexe

[Métodos] Conversiones de fechas

Para convertir estos tipos de fecha, tenemos una ruta preparada y en gral empleo una clase para luego importarla, crear un objeto y usar sus metodos:




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class Conversionador {
    public String date2String(Date miDate, String formato){
        SimpleDateFormat sdf = new SimpleDateFormat(formato);
        String miString = sdf.format(miDate);
        return miString;
    }
    public Date string2Date(String miString, String formato) throws ParseException{
        SimpleDateFormat sdf = new SimpleDateFormat(formato);
        Date miDate = sdf.parse(miString);
        return miDate;
    }

    public String calendar2String(Calendar miCalendar10, String formato){
        SimpleDateFormat sdf = new SimpleDateFormat(formato);
        String miString = sdf.format(miCalendar10.getTime());
        return miString;
    }
    public Calendar string2Calendar(String miString, String formato) throws ParseException{
        SimpleDateFormat sdf = new SimpleDateFormat(formato);
        Calendar miCalendar10 = Calendar.getInstance();
        miCalendar10.setTime(sdf.parse(miString));
        return miCalendar10;
    }

    public Date calendar2Date(Calendar miCalendar10){
        Date miDate = miCalendar10.getTime();
        return miDate;
    }
    public Calendar date2Calendar(Date miDate){
        Calendar miCalendar10 = Calendar.getInstance();
        miCalendar10.setTime(miDate);
        return miCalendar10;
    }
}

Con esta clase y estos métodos seremos capaz de convertir entre:

  • Date2String(Date miDate, String formato) (Date a String)
    • Parámetros:
      • miDate: el Date a convertir
      • formato: el formato que tendrá el String resultante.
  • String2Date(String miString, String formato) (String a Date)
    • Parámetros:
      • miString: el String a convertir
      • formato: el formato que tiene el String que convertiremos.
    • Arroja
    • ParseException

  • calendar2String(Calendar miCalendar10, String formato) (Calendar a String)
    • Parámetros
      • miCalendar10: el calendario a convertir a String
      • formato: el formato que tendrá el String resultante.
  • string2Calendar(String miString, String formato)
    • Parámetros
      • miString: el String que convertiremos a Calendar
      • formato: el formato que tiene el String que convertiremos.
    • Arroja
    • ParseException
  • calendar2Date(Calendar miCalendar10)
    • Parámetro
      • miCalendar10: el calendario a convertir a Date
  • date2Calendar(Date miDate)
    • Parámetros
      • miDate: el Date que convertiremos a Calendar

  • [Métodos] Obtener fecha y hora - Formatos de fechas - Conversiones (Parte II)

    Obtener fecha y hora - Formatos de fechas


    DateFormat


    DateFormat es una clase abstracta para el formateo de fecha y hora de otras clases(Calendar-Date-String)

    Habrá que instanciar un objeto de esta clase a través de su método getDateInstance() sin parámetros y/o con uno de los formatos que trae incluidos y/o un objeto Locale adecuado.
    Dependiendo de la especificación geográfica, cultura y politica (objeto Locale) variará el formato de fecha.
    Para estos casos, suelo usar el métodos sin parámetros, que tomará por defecto la posición y formato y además también crear el objeto Locale propio:

      DateFormat df0 = DateFormat.getDateInstance();

      Locale local = new Locale("es");
      DateFormat df1 = DateFormat.getDateInstance(DateFormat.LONG, local);

    Formatos


    Aun que esto varié enormemente dependiendo del lenguaje, para los casos sin parámetros(Default) y con el Locale en español los formatos serían:

    Constante Formato Valor Ejemplo
    default dd/MM/yyyy null 23/07/2016
    DateFormat.LONG dd 'de' MMMM 'de' yyyy 1 23 de julio de 2016
    DateFormat.MEDIUM dd-MMM-yyyy 2 23-jul-2016
    DateFormat.SHORT dd/MM/yy 3 23/07/16

    Conversiones



     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     // CREO UN OBJECTO DATE ACTUAL
     Date miDate = new Date();
     // CREO UN STRING DE OTRA FECHA CON EL FORMATO 'LONG'
     String miString = "16 de enero de 1989";
    
     // CREO UN 'LOCALE' Y UN 'DATEFORMAT'
     Locale local = new Locale("es");
     DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, local);
    
     // HAGO LAS CONVERSIONES
     String fechastr = df.format(miDate);
     Date fechadate = df.parse(miString);
     // OBTENGO UN CALENDARIO DE LA FECHA ACTUAL
     Calendar cal = df.getCalendar();
    
     // MUESTRO POR PANTALLA
     System.out.println("De string a Date: " + fechastr);
     System.out.println("De Date a String: " + fechadate);
     System.out.println("Objeto Calendar del momento " + cal.toString());
    

      De string a Date: 23 de julio de 2016
      De Date a String: Mon Jan 16 00:00:00 ARST 1989
      Objeto Calendar del momento java.util.GregorianCalendar[...]





    SimpleDateFormat


    SimpleDateFormat es sub-clase de DateFormat y clase concreta.
    Ademas de poder un objeto de ella, en su constructor podemos pasarle el patron de fecha que deseamos obtener:

    Patrones de Fecha y Hora


    Patron de Letra Descripción Presentacion Ejemplos
    G Designador de ERA Texto AD
    y Año Año 1996; 96
    Y Año Año 2009; 09
    M Mes en el Año Mes July; Jul; 07
    w Semana en el Año Número 27
    W Semana en el Mes Número 2
    D Dia en el Año Número 189
    d Dia en el Mes Número 10
    F Dia de la Semana en el Mes Número 2
    E Nombre del Dia en la Semana Texto TuesDay; Tue
    u Númerp de Dia de la Semana (1 = MonDay, ..., 7 = SunDay) Número 1
    a Marca Am/pm Texto PM
    H Hora en el Dia (0-23) Número 0
    k Hora en el Dia (1-24) Número 24
    K Hora en la marca am/pm (0-11) Número 0
    h Hora en la marca am/pm (1-12) Número 12
    m Minutos en la Hora Número 30
    s Segundos en el Minutos Número 55
    S MilliSegundos Número 978
    z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
    Z Time zone RFC 822 time zone -0800
    X Time zone ISO 8601 time zone -08; -0800; -08:00

    Para introducir los caracteres como texto los escapeamos con comillas simples, por ejemplo:

    • 25 de mayo de 1810
    • dd 'de' MMMM 'de' yyyy


    Luego es exactamente igual que trabajar con DateFormat , salvo que esta vez creamos el objeto con su constructor pero y en el formato somos libre de crear como querramos que salga el String y/o venga.
    También obviaremos la parte del objeto Locale.


     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
     // CREAMOS FECHAS
     Date miDate = new Date();
     String miString = "16/01/1989";
     
     // CREAMOS EL FORMATEADOR
     SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
     
     // CONVERSIONES
     String fechaString = sdf.format(miDate);
     Date fechaDate = sdf.parse(miString);
     Calendar cal = sdf.getCalendar();
    
     // SALIDA POR PANTALLA
     System.out.println(fechaString);
     System.out.println(fechaDate);
     System.out.println(cal);
    

    [Métodos] Obtener fecha y hora - Formatos de fechas - Conversiones (Parte I)

    Obtener fecha y hora - Formatos de fechas


    Para obtener la fecha y hora en java hay varias clases utiles para hacerlo:

    java.util.Calendar public abstract class Calendar extends Object implements Serializable, Cloneable, Comparable<calendar>
    java.util.GregorianCalendar public class GregorianCalendar extends Calendar
    java.util.Date public class Date extends Object implements Serializable, Cloneable, Comparable
    java.sql.Date public class Date extends Date


    Clase Calendar


    Clase abstracta que puede ser instancia a través del método de clase getInstance()
    Cuenta con un sin fin de atributos estaticos del tipo 'int' y métodos que podremos ir obteniendo con la fecha y hora actual del sistema.

    Bastará con declarar la clase y darle un nombre, llamar a la misma clase para que ejecute el método.
    Luego ya podremos usar el objeto para ir obteniendo los atributos de la clase que corresponde a cada magnitud de tiempo:
    el formato que le doy para mostrar es hh:MM:ss.SS a dd/mm/yyyy era



    Calendar miCalendar10 = Calendar.getInstance();
    System.out.print(miCalendar10.get(Calendar.HOUR) +":");
    System.out.print(miCalendar10.get(Calendar.MINUTE) +":");
    System.out.print(miCalendar10.get(Calendar.SECOND) +".");
    System.out.print(miCalendar10.get(Calendar.MILLISECOND) +" ");
    System.out.print(miCalendar10.get(Calendar.AM_PM) +" ");
    System.out.print(miCalendar10.get(Calendar.DATE) +"/");
    System.out.print(miCalendar10.get(Calendar.MONTH) +"/");
    System.out.print(miCalendar10.get(Calendar.YEAR) +" ");
    System.out.print(miCalendar10.get(Calendar.ERA);


    La salida por pantalla tendria la pinta:

      10:7:17.956 1 19/6/2016 1

    Dado que la clase Calendar solo nos devuelve variables primitivas del tipo int, hará falta pulir un poco la salida para obtener el formato deseado:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
      Calendar miCalendar10 = Calendar.getInstance();
    
      int hora = miCalendar10.get(Calendar.HOUR);
      String _hora = hora > 9 ? "" + hora : ("0"+ hora); 
      System.out.print(_hora + ":");
    
      int minutos = miCalendar10.get(Calendar.MINUTE);
      String _minutos = minutos > 9 ? "" + minutos : "0" + minutos; 
      System.out.print( _minutos + ":");
    
      int segundos = miCalendar10.get(Calendar.SECOND);
      String _segundos = segundos > 9 ? "" + segundos : "0" + segundos;
      System.out.print(_segundos +".");
    
      int milisegundos = miCalendar10.get(Calendar.MILLISECOND);
      String _milisegundos = milisegundos > 9 ? "" + milisegundos : "0" + milisegundos;
      System.out.print( _milisegundos +" ");
    
      if(miCalendar10.get(Calendar.AM_PM) == 0)
     System.out.print("AM ");
      else
     System.out.print("PM ");
    
      int dia = miCalendar10.get(Calendar.DATE);
      String _dia = dia > 9 ? "" + dia : ("0"+ dia); 
      System.out.print(_dia + "/");
    
      int mes = miCalendar10.get(Calendar.MONTH) + 1;
      String _mes = mes > 9 ? "" + mes : ("0"+ mes); 
      System.out.print(_mes + "/");
    
      System.out.print(miCalendar10.get(Calendar.YEAR) +" ");
    
      if(miCalendar10.get(Calendar.ERA) == 0)
     System.out.println("A.C.");
      else
     System.out.println("D.C.");
    

    La salida ahora por pantalla al editarlo un poquito tendrá algo de Strings, asegurandonos completar las unidades con un cero adelante.

      10:07:17.956 PM 19/06/2016 D.C.

    Para poder ver el método toString() de la propia clase, podriamos hacer algo similar a:



    Calendar miCalendar10 = Calendar.getInstance();
    String str = miCalendar10.toString();
    str = str.substring(str.indexOf("time"), str.length() -1 );
    String[] array = str.split(",");
    for(String cadena : array)
        System.out.println(cadena);



    Obteniendo algo como:

      time=1468978267659
      areFieldsSet=true
      areAllFieldsSet=true
      lenient=true
      zone=sun.util.calendar.ZoneInfo[id="America/Buenos_Aires"
      offset=-10800000
      dstSavings=0
      useDaylight=false
      transitions=62
      lastRule=null]
      firstDayOfWeek=2
      minimalDaysInFirstWeek=1
      ERA=1
      YEAR=2016
      MONTH=6
      WEEK_OF_YEAR=30
      WEEK_OF_MONTH=4
      DAY_OF_MONTH=19
      DAY_OF_YEAR=201
      DAY_OF_WEEK=3
      DAY_OF_WEEK_IN_MONTH=3
      AM_PM=1
      HOUR=10
      HOUR_OF_DAY=22
      MINUTE=31
      SECOND=7
      MILLISECOND=659
      ZONE_OFFSET=-10800000
      DST_OFFSET=0

    Desde luego la clase calendar no es la mas recomendada para obtener la fecha y hora.




    Clase GregorianCalendar


    GregorianCalendar es una subclase concreta de Calendar y proporciona el sistema de calendario estándar utilizado por la mayoría del mundo.
    GregorianCalendar es un calendario híbrido que es compatible tanto con los sistemas Gregorianos y Julianos del calendario con el apoyo de una sola discontinuidad, lo que corresponde de forma predeterminada a la fecha gregoriana, cuando se instituyó el calendario gregoriano (15 de octubre de 1582, en algunos países, más adelante en otros). La fecha de corte puede ser cambiado por el de llamada llamando setGregorianChange ().

    Esta clase tiene varias formas de ser instanciada:
    • Llamando al método de clase de Calendar para instanciar, y realizar un pequeño casteo.
    • Pasandole a su constructor los parámetros:
      • Enteros ('int') correspondientes a el año, mes, dia, hora, minuto y segundo
      • Un objeto de la clase java.util.Locale
      • Otro objeto de la clase java.util.TimeZone

    1
    2
    3
    4
    5
    6
    GregorianCalendar gc1 = (GregorianCalendar) Calendar.getInstance();
    GregorianCalendar gc2 = new GregorianCalendar(2016, 07, 22);
    Locale local = new Locale("es");
    GregorianCalendar gc3 = new GregorianCalendar(local);
    TimeZone tz = TimeZone.getTimeZone("America/Buenos_Aires");
    GregorianCalendar gc4 = new GregorianCalendar(tz);
    

    De encapsular el método que nos valia para la clase Calendar, obtendriamos el mismo resultado.

    1
    2
    3
    4
    5
    6
    7
    public static void separarAtributos(Calendar gc) {
        String aux = gc.toString().substring(28, gc.toString().length() - 1);
        String[] array = aux.split(",");
        for (String data : array) {
     System.out.println(data);
     }
    }
    

    De la misma forma que su predecesor, GregorianCalendar es otra clase para generar un objeto e ir extrayendo propiedad a propiedad en el caso que querramos solo una o unas pocas en especial.

      System.out.println(gc.get(GregorianCalendar.MONTH));




    Clase util.Date


    La clase java.util.Date es la mas util de todas. Bastará con crear el objeto y dispondremos de un objeto de fechas con el siguiente formato:

      EEE MMM dd HH:mm:ss zzz yyyy
      Fri Jul 22 12:20:00 ART 2016

    Es un formato muy util y rápido en 1 sola linea si la intencion es obtener un formato de dia-mes-año
    1
    2
    Date() miDate = new Date();
    System.out.println(miDate);
    

    Se podrían obtener los campos de fechas de manera indivual pero están todos deprecados de la JDK version 1.1(funcionan pero no es recomendado).
    En su lugar recomiendan usar la clase abstracta java.util.Calendar para obtener las fechas indivudualmente:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Date date = new Date();
    
    // NO ES RECOMENDABLE
    System.out.println(date.getMonth());
    
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    
    System.out.println(cal.get(Calendar.MONTH));
    

    Para lo cual si hemos de obtener los atributos por separados, hay que recordar que el metodo setTime(Date d) de la clase Calendar recibe por parámetro a el objeto Date del cual queremos extraer la información.



    Clase sql.Date


    Date exactamente igual pero del paquete sql es subClase de la clase con mismo nombre del paquete util. Tiene 2 constructores para setear con parámetros enteros ('int') el año-mes-dia (Pero esta deprecada y no es recomendable su uso.
    1
    2
    3
    Date sqlDate = new Date(2016, 07, 22);
    
    System.out.println(sqlDate.getMonth());
    

    Y otro constructor estable, que recibe como parámetro un parámetro del tipo 'long' que representa los milisegundos que pasaron desde el 1ro de enero de 1970.
    Si sos de las personas que no llevan la cuenta, un atributo de la clase calendar nos la dice por nosotros:

    1
    2
    3
    4
    5
    6
    Calendar cal = Calendar.getInstance();
    long ms = cal.getTimeInMillis();
    
    Date sqlDate = new Date(ms);
    
    System.out.println(sqlDate);
    

    Al hacerlo obtendremos como resultado el formato mas utilizado en base de datos y no será necesario preocuparnos por el formato adecuado: (yyyy-MM-dd)

      2016-07-22





    [GIT] Ramas - Branch


    Ramas


    Un 'branch' (rama) en git es simplemente un apuntador móvil a un commit.
    La rama por defecto que GIT crea por nosotros es la rama 'master'
    Como buenas practicas, deberia ser ésta la versión estable de la aplicación y deberá usarse otras para el desarrollo.

    Con la primera confirmación de cambios, se creará automaticamente apuntando a el commit realizado. A medida que realicemos mas confirmaciones de cambios la rama irá avanzando sola y 'master' irá puntando siempre al ultimo commit hecho.


    ¿Qué sucede si creamos una nueva rama?


    Se creara un nuevo apuntador para que se pueda mover libremente sin afectar a 'master', todas las modificaciones y commits que hagamos 'master' no las verá reflejas.
    En la siguiente imagen se ven 3 commits realizados(en verde) a los cuales tanto la rama 'master' puede verlos y la nueva rama 'testing' tambien, pero de aqui en mas harán camino separados.



    Para crear una nueva rama utilizamos branch seguido del nombre de la nueva rama:

      $ git branch testing

    Por defecto git branch listara todas las ramas existente, al igual que con el parametro --list

    ¿Cómo sabemos entonces en que rama estamos parado?


    Al ejecutar el comando git branch debemos obtener algo similiar a :

      $ git branch
      * master
        testing

    Pero existe un apuntador especial llamado HEAD (Cabeza) que apunta a la rama local actual.
    Para poder intercambiar de ramas se utliza el comando chekout

      $ git checkout testing
      Switched to branch 'testing'

    Ahora la situacion del repositorio a pasado, a tener 2 ramas, y se ha movido el HEAD a 'testing'




    Tambien podremos observar que en la lineas de comandos donde se encuetra el repositorio a cambio de (master) a (testing) indicando en que rama estamos parado:




    La idea de branches se clarifica mas al continuar realizando commiteos en esta nueva rama. Una forma rápita de realizar muchos commits es hacerlos vacios, lo cual no tiene mucho sentido pero en este caso de aprendizaje es ideal, para hacerlo:

      $ git commit --allow-empty -m "1er commit vacio"
      [testing 29fa38e] 1er commit vacio

    Ahora la situación gráficamente se vuelve:



    Hay que notar que la rama testing avanza, mientra que master continua en el ultimo commit que se realizó.
    Si nos movemos a la rama master...

      $ git checkout master

    Al realizar este comando estariamos movilizando el HEAD al ultimo commit realizado en master, pudiendo observar todos los commits que realizaron aqui, pero no las modificaciones realizadas en testing.



    Este comando realiza 2 aciones en simultaneo:
    • Mueve el apuntador HEAD a la rama master.
    • Revierte los archivos de tu directorio de trabajo al momento de realizar el ultimo commit en master
    Esto supone que los cambios realizados de acá en adelante solo rigiran para la rama master y solo en esta dirección.
    De continuar trabajando sobre esta rama, se revierte las modificaciones hechas en testing y habra 2 versiones de un mismo proyecto.
    Al realizar modificaciones, incluirlas en el staging index, y confirmar los cambios, la situacion gráficamente se verá tal como:




    Una rama en git es solamente un archivo que contiene 40 caracteresde una suma de control SHA-1 (basado en el contenido de los archivos y no en su metadata) no cuesta nada al construir y destruir ramas en GIT.

    Esto aventaja a GIT como software de control de versiones, ya que otros para crear una rama nueva, se necesitaba copiar el contenido existente del ultimo commit, y depediendo del proyecto podria tardar minutos si es lo suficientemente grande.
    Para GIT es rápido y sencillo, solo le lleva 41 bytes entre los 40 caracteres y un retorno de carro.

    Diferentes formas de llamar a un branch


    Existen varias formas de apuntar a un branch:
    • A través de su nombre:
      • $ git branch master
    • A través de su codigo abreviado de 7 caracteres:
      • $ git branch 29fa38e
    • A través de su codigo de 40 caracteres:
      • $ git branch 29fa38e8b214015dc6e289d13e802b346b66d931
    • A través del HEAD si este lo esta apuntando:
      • $ git branch HEAD
    • Y atraves de los operadores de GIT



    Fusión de Branchs (Merge)


    Unificar ramas supone haber cumplido con la tarea (issue, track, ticket, etc), la cual nos incentivo a generar la rama en si. Pero esta fusión de ramas trae aparejada que estrategia seguir ya que no todos los casos de repositorios son iguales:
    • Podriamos tener una branch con commits hechos a partir de la separación y el otro no.
    • Tener un branch con archivos 'a', 'b', 'c' y el otro con 'd', 'e' y 'g'.
    • O podriamos tener los mismos archivos pero de diferentes tamaños y con distintas metadata.


    Basicamente nuestro procedimiento deberia de ser:
    • Creamos una rama a partir de otra
      • $ git branch test
    • Realizamos nuestra tarea, requerimiento, etc
      • Trabajando =)
    • Comprometemos los cambios
      • $ git commit -m "implementacion hecha"
    • Nos movemos a la rama para fusionar sobre la que trabajamos(gralmente suele fusionarse contra master)
      • $ git checkout master
    • Realizamos el mergeo
      • $ git merge test
    • También en este punto podríamos eliminar la rama que ya no necesitaremos
      • $ git branch -d test


    Ahora, después que nuestro merge se realiza con éxito en nuestro repositorio puede darse dos posibles casos:
    • Una unión de ramas con una estrategia fast-forward(avance rápido)
    • O ua estrategia 3-way (merge a tres bandas).

    Fast-Forward (ff)


    La estrategia de fast-forward es cuando al momento de hacer el nuevo brnach, se deja de hacer modificaciones en master y por ende al momento de mergear solo se le incluyen los commits de la rama altenativa como propia.
    Para GIT lo unico que hace es mover el HEAD de master a el HEAD del nuevo branch:


    Tambien existe el caso, de hacer un commit al momento de hacer el merge poniendo los parametros --no-ff en el comando para hacer la union de ramas.

      $ git merge --no-ff test

    Visualmente el repositorio quedaría asi:


    Three ways (3-way)


    Pero por otro lado, si al momento de hacer el mergeo, exiten mas confirmaciones de cambio en una de las ramas, (master en nuestro caso) nya no podra ser posible la estrategia fast-forward y será necesario hacer un commit (como en el caso anterior --no-ff) para unificar las ramas:


    GIT realiza un merge 3-way (tres bandas), es decir que genera un 'commit' para unificar las ramas, tomando en cuenta el HEAD de cada una de ellas y el antepasado común, de ahi su nombre.
    De aquí en mas, dependiendo del proyecto, será necesaria la intervención humana para la resolución de conflictos y decidir con cual archivo conflictivo quedarnos, del mismo que al pegar el contenido de una carpeta nuestro sistema operativo nos advierte y nos da la opcion de reemplazar u omitir.

    Por ejemplo al intentar fusionar 2 branchs (master y feature) con un solo archivo llamado README.txt donde varian el contenido en una sola linea, la consola se veria de la siguiente forma:

      $ git merge feature
      Auto-merging README.txt
      CONFLICT (content): Merge conflict in README.txt
      Automatic merge failed; fix conflicts and then commit the result.

      $ git status
      On branch master
      You have unmerged paths.
          (fix conflicts and run "git commit")
     
      Unmerged paths:
          (use "git add ..." to mark resolution)
     
               both modified: README.txt
     
      no changes added to commit (use "git add" and/or "git commit -a")

      $ git diff
      diff --cc README.txt
      index 6007a7c,e8d6d88..0000000
      --- a/README.txt
      +++ b/README.txt
      @@@ -1,1 -1,1 +1,5 @@@
     
      ++<<<<<<< HEAD
      +Unica linea en master
      ++=======
      + linea conflictiva de feature

      ++>>>>>>> feature

      $ git commit -a
      [master caaf175] Merge branch 'feature'

    Al realizar esta acción forzamos a realizar el mergeo, simplemente nos genera un archivo "híbrido" con el contenido de ambos, tal como nos muestra en la consola, resultado final es:

      <<<<<<< HEAD
     +Unica linea en master
     + linea conflictiva de feature
     ++>>>>>>> feature

    Por lo cual es recomendable realizar al obtener el error de merge, modificar el archivo tal como queremos, en este caso bastara con:

      $ vim README.txt
      <<<<<<< HEAD
     +Unica linea en master
     + linea conflictiva de feature
     ++>>>>>>> feature

    'i' para editar:

     +Unica linea en master

    salimos con esc ':wq'


    Resolviendo conflictos: Ours - Theirs


    Otra manera de resolver estos conflictos, es avisarle a GIT con cual archivo queremos quedarnos sabiendo o no que pueden haber conflicto, con ours(nuestros) y theirs(suyos) hablando de cambios.

      $ git merge -s recursive -X ours testing

    o

      $ git merge -s recursive -X theirs testing

    Cancelando un merge


    Tal como nos decia la ayuda, si al momento de hacer un merge nos rejectea podemos deshacer los nuevos cambios con:

      $ git merge --abort

    Deshaciendo un merge


    Para deshacer un merge, podemos intentar:

      $ git reset --merge ORIG_HEAD