¿Cómo obtener el primer día de la semana y mes actuales?

Tengo la fecha de varios eventos expresados ​​en milisegundos [1], y quiero saber qué eventos están dentro de la semana actual y el mes actual, pero no puedo entender cómo obtener el primer día (día / mes / año). ) de la semana en curso y convertirlo a milisegundos, lo mismo para el primer día del mes.

[1]Since January 1, 1970, 00:00:00 GMT 

Esta semana en milisegundos:

 // get today and clear time of day Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day ! cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); // get start of this week in milliseconds cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); System.out.println("Start of this week: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); // start of the next week cal.add(Calendar.WEEK_OF_YEAR, 1); System.out.println("Start of the next week: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); 

Este mes en milisegundos:

 // get today and clear time of day Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day ! cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); // get start of the month cal.set(Calendar.DAY_OF_MONTH, 1); System.out.println("Start of the month: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); // get start of the next month cal.add(Calendar.MONTH, 1); System.out.println("Start of the next month: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); 

El primer día de la semana se puede determinar con la ayuda de java.util.Calendar siguiente manera:

 Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setTimeInMillis(timestamp); while (calendar.get(Calendar.DAY_OF_WEEK) > calendar.getFirstDayOfWeek()) { calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of week. } long firstDayOfWeekTimestamp = calendar.getTimeInMillis(); 

El primer día del mes se puede determinar de la siguiente manera:

 Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setTimeInMillis(timestamp); while (calendar.get(Calendar.DATE) > 1) { calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of month. } long firstDayOfMonthTimestamp = calendar.getTimeInMillis(); 

Bastante detallado, sí.


Java 7 vendrá con una API de fecha y hora mucho mejor ( JSR-310 ). Si aún no puede cambiar, puede usar JodaTime, lo que lo hace todo menos complicado:

 DateTime dateTime = new DateTime(timestamp); long firstDayOfWeekTimestamp = dateTime.withDayOfWeek(1).getMillis(); 

y

 DateTime dateTime = new DateTime(timestamp); long firstDayOfMonthTimestamp = dateTime.withDayOfMonth(1).getMillis(); 

¡Atención!

 while (calendar.get(Calendar.DAY_OF_WEEK) > calendar.getFirstDayOfWeek()) { calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of week. } 

es una buena idea, pero hay un problema: por ejemplo, soy de Ucrania y calendar.getFirstDayOfWeek () en mi país es 2 (lunes). Y hoy es 1 (domingo). En este caso, no se llamó a calendar.add.

Entonces, la forma correcta es cambiar “>” a “! =”:

 while (calendar.get(Calendar.DAY_OF_WEEK) != calendar.getFirstDayOfWeek()) {... 

java.time

El framework java.time en Java 8 y posterior suplanta las antiguas clases java.util.Date/.Calendar. Las viejas clases han demostrado ser problemáticas, confusas y defectuosas. Evítales.

El framework java.time está inspirado en la exitosa librería Joda-Time , definida por JSR 310 , extendida por el proyecto ThreeTen-Extra , y explicada en el Tutorial .

Instant

La clase Instant representa un momento en la línea de tiempo en UTC .

El marco java.time tiene una resolución de nanosegundos, o 9 dígitos de una fracción de segundo. Milisegundos tiene solo 3 dígitos de una fracción de segundo. Debido a que la resolución de milisegundos es común, java.time incluye un práctico método de fábrica.

 long millisecondsSinceEpoch = 1446959825213L; Instant instant = Instant.ofEpochMilli ( millisecondsSinceEpoch ); 

milisegundosDesdeEpoch: 1446959825213 es instantáneo: 2015-11-08T05: 17: 05.213Z

ZonedDateTime

Para considerar la semana actual y el mes actual, necesitamos aplicar un huso horario en particular.

 ZoneId zoneId = ZoneId.of ( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId ); 

En zoneId: America / Montreal que es: 2015-11-08T00: 17: 05.213-05: 00 [America / Montreal]

Medio abierto

En el trabajo de fecha y hora, comúnmente utilizamos el enfoque de Medio Abierto para definir un lapso de tiempo. El comienzo es inclusivo mientras que el final es exclusivo . En lugar de tratar de determinar la última fracción de segundo del final de la semana (o mes), obtenemos el primer momento de la semana (o mes) siguiente. Entonces, una semana se extiende desde el primer momento del lunes hasta el primer lunes del lunes siguiente, pero sin incluirlo .

Vamos el primer día de la semana y el último. El framework java.time incluye una herramienta para eso, el método with y el enum de ChronoField .

Por defecto, java.time usa el estándar ISO 8601 . Entonces, el lunes es el primer día de la semana (1) y el domingo es el último (7).

 ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week. ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 ); 

Esa semana se extiende desde: 2015-11-02T00: 17: 05.213-05: 00 [America / Montreal] a 2015-11-09T00: 17: 05.213-05: 00 [America / Montreal]

Oops! Mire la hora del día en esos valores. Queremos el primer momento del día. El primer momento del día no siempre es 00:00:00.000 debido al horario de verano (DST) u otras anomalías. Entonces deberíamos dejar que java.time realice el ajuste en nuestro nombre. Para hacer eso, debemos pasar por la clase LocalDate .

 ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week. firstOfWeek = firstOfWeek.toLocalDate ().atStartOfDay ( zoneId ); ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 ); 

Esa semana se extiende desde: 2015-11-02T00: 00-05: 00 [America / Montreal] a 2015-11-09T00: 00-05: 00 [America / Montreal]

Y lo mismo para el mes.

 ZonedDateTime firstOfMonth = zdt.with ( ChronoField.DAY_OF_MONTH , 1 ); firstOfMonth = firstOfMonth.toLocalDate ().atStartOfDay ( zoneId ); ZonedDateTime firstOfNextMonth = firstOfMonth.plusMonths ( 1 ); 

Ese mes se extiende desde: 2015-11-01T00: 00-04: 00 [America / Montreal] a 2015-12-01T00: 00-05: 00 [America / Montreal]

YearMonth

Otra forma de ver si un par de momentos está en el mismo mes es verificar el mismo valor de YearMonth .

Por ejemplo, suponiendo que thisZdt y thatZdt son objetos ZonedDateTime :

 boolean inSameMonth = YearMonth.from( thisZdt ).equals( YearMonth.from( thatZdt ) ) ; 

Milisegundos

Recomiendo encarecidamente no realizar su trabajo de fecha y hora en milisegundos a partir de la época. Esa es de hecho la forma en que las clases de fecha y hora tienden a funcionar internamente, pero tenemos las clases por una razón. Manejar una cuenta a partir de la época es torpe ya que los valores no son inteligibles para los humanos, por lo que la depuración y el registro son difíciles y propensos a errores. Y, como ya hemos visto, diferentes resoluciones pueden estar en juego; las antiguas clases Java y la biblioteca Joda-Time usan milisegundos, mientras que las bases de datos como Postgres usan microsegundos, y ahora java.time usa nanosegundos.

¿Manejaría el texto como bits, o permitiría que clases como String , StringBuffer y StringBuilder manejaran tales detalles?

Pero si insistes, desde un ZonedDateTime obtienes un Instant , y de ahí obtienes un milisegundo-count-from-epoch. Pero tenga en cuenta que esta llamada puede significar pérdida de datos . Cualquier microsegundo o nanosegundo que pueda tener en su ZonedDateTime / Instant se truncará (se perderá).

 long millis = firstOfWeek.toInstant().toEpochMilli(); // Possible data loss. 

Para obtener el primer día del mes, simplemente obtenga una Date y configure el día actual al día 1 del mes. Borrar hora, minuto, segundo y milisegundos si lo necesita.

 private static Date firstDayOfMonth(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.DATE, 1); return calendar.getTime(); } 

El primer día de la semana es lo mismo, pero usando Calendar.DAY_OF_WEEK

 private static Date firstDayOfWeek(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.DAY_OF_WEEK, 1); return calendar.getTime(); } 

En este caso:

 // get today and clear time of day Calendar cal = Calendar.getInstance(); cal.clear(Calendar.HOUR_OF_DAY); <---- is the current hour not 0 hour cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); 

Entonces, Calendar.HOUR_OF_DAY devuelve 8, 9, 12, 15, 18 como la hora stream. Creo que será mejor cambiar esa línea por:

 c.set(Calendar.HOUR_OF_DAY,0); 

de esta forma el día siempre comienza a las 0 horas

Debería poder convertir su número a un calendario Java, por ejemplo:

  Calendar.getInstance().setTimeInMillis(myDate); 

A partir de ahí, la comparación no debería ser demasiado difícil.

 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Scanner; /** This Program will display day for, 1st and last days in a given month and year @author Manoj Kumar Dunna Mail Id : manojdunna@gmail.com */ public class DayOfWeek { public static void main(String[] args) { String strDate = null; int year = 0, month = 0; Scanner sc = new Scanner(System.in); System.out.print("Enter YYYY/MM: "); strDate = sc.next(); Calendar cal = new GregorianCalendar(); String [] date = strDate.split("/"); year = Integer.parseInt(date[0]); month = Integer.parseInt(date[1]); cal.set(year, month-1, 1); System.out.println(new SimpleDateFormat("EEEE").format(cal.getTime())); cal.add(Calendar.MONTH, 1); cal.add(Calendar.DAY_OF_YEAR, -1); System.out.println(new SimpleDateFormat("EEEE").format(cal.getTime())); } } 
 Simple Solution: package com.util.calendarutil; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; public class CalUtil { public static void main(String args[]){ DateFormat df = new SimpleDateFormat("dd/mm/yyyy"); Date dt = null; try { dt = df.parse("23/01/2016"); } catch (ParseException e) { System.out.println("Error"); } Calendar cal = Calendar.getInstance(); cal.setTime(dt); cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); Date startDate = cal.getTime(); cal.add(Calendar.DATE, 6); Date endDate = cal.getTime(); System.out.println("Start Date:"+startDate+"End Date:"+endDate); } } 

He creado algunos métodos para esto:

 public static String catchLastDayOfCurrentWeek(String pattern) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); return calendarToString(cal, pattern); } public static String catchLastDayOfCurrentWeek(String pattern) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); cal.add(Calendar.WEEK_OF_YEAR, 1); cal.add(Calendar.MILLISECOND, -1); return calendarToString(cal, pattern); } public static String catchTheFirstDayOfThemonth(Integer month, pattern padrao) { Calendar cal = GregorianCalendar.getInstance(); cal.setTime(new Date()); cal.set(Calendar.MONTH, month); cal.set(Calendar.DAY_OF_MONTH, 1); return calendarToString(cal, pattern); } public static String catchTheLastDayOfThemonth(Integer month, String pattern) { Calendar cal = GregorianCalendar.getInstance(); cal.setTime(new Date()); cal.set(cal.get(Calendar.YEAR), month, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); return calendarToString(cal, pattern); } public static String calendarToString(Calendar calendar, String pattern) { if (calendar == null) { return ""; } SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE); return format.format(calendar.getTime()); } 

Puedes ver más aquí .

Obtenga la primera fecha del próximo mes : –

 SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy"); String selectedDate="MM-dd-yyyy like 07-02-2018"; Date dt = df.parse(selectedDate);`enter code here` calendar = Calendar.getInstance(); calendar.setTime(dt); calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1); String firstDate = df.format(calendar.getTime()); System.out.println("firstDateof next month ==>" + firstDate); 
 public static void main(String[] args) { System.out.println(getMonthlyEpochList(1498867199L,12,"Monthly")); } public static Map getMonthlyEpochList(Long currentEpoch, int noOfTerms, String timeMode) { Map map = new LinkedHashMap(); int month = 0; while(noOfTerms != 0) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MONTH, month); calendar.set(Calendar.DATE, calendar.getActualMinimum(Calendar.DAY_OF_MONTH)); Date monthFirstDay = calendar.getTime(); calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); Date monthLastDay = calendar.getTime(); map.put(getMMYY(monthFirstDay.getTime()), monthFirstDay + ":" +monthLastDay); month--; noOfTerms--; } return map; }