/*
* OffenePflege
* Copyright (C) 2006-2012 Torsten Löhr
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License V2 as published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to
* the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
* www.offene-pflege.de
* ------------------------
* Auf deutsch (freie Übersetzung. Rechtlich gilt die englische Version)
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License,
* wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, gemäß Version 2 der Lizenz.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber
* OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN
* BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
*
* Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht,
* schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
*
*/
package op.tools;
import com.toedter.calendar.JDateChooser;
import entity.system.SYSPropsTools;
import gui.GUITools;
import io.lamma.LammaConst;
import io.lamma.Month;
import io.lamma.Weekday;
import op.OPDE;
import op.threads.DisplayMessage;
import org.apache.commons.collections.Closure;
import org.joda.time.DateMidnight;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.*;
public class SYSCalendar {
// Both for DFN and BHP
public static final byte SHIFT_OUTCOMES = -2;
public static final byte SHIFT_ON_DEMAND = -1;
public static final byte SHIFT_VERY_EARLY = 0;
public static final byte SHIFT_EARLY = 1;
public static final byte SHIFT_LATE = 2;
public static final byte SHIFT_VERY_LATE = 3;
public static final Byte[] SHIFTS = new Byte[]{SHIFT_VERY_EARLY, SHIFT_EARLY, SHIFT_LATE, SHIFT_VERY_LATE};
public static final byte BYTE_TIMEOFDAY = 0;
public static final byte BYTE_EARLY_IN_THE_MORNING = 1;
public static final byte BYTE_MORNING = 2;
public static final byte BYTE_NOON = 3;
public static final byte BYTE_AFTERNOON = 4;
public static final byte BYTE_EVENING = 5;
public static final byte BYTE_LATE_AT_NIGHT = 6;
public static final String STRING_TIMEOFDAY = "UZ";
public static final String STRING_EARLY_IN_THE_MORNING = "FM";
public static final String STRING_MORNING = "MO";
public static final String STRING_NOON = "MI";
public static final String STRING_AFTERNOON = "NM";
public static final String STRING_EVENING = "AB";
public static final String STRING_LATE_AT_NIGHT = "NA";
public static final String[] SHIFT_KEY_TEXT = new String[]{"VERY_EARLY", "EARLY", "LATE", "VERY_LATE"};
public static final String[] SHIFT_TEXT = new String[]{"msg.shift.veryearly", "msg.shift.early", "msg.shift.late", "msg.shift.verylate"};
public static final String[] TIMEIDTEXTLONG = new String[]{"misc.msg.Time.long", "misc.msg.earlyinthemorning.long", "misc.msg.morning.long", "misc.msg.noon.long", "misc.msg.afternoon.long", "misc.msg.evening.long", "misc.msg.lateatnight.long"};
public static final String[] TIMEIDTEXTSHORT = new String[]{"misc.msg.Time.short", "misc.msg.earlyinthemorning.short", "misc.msg.morning.short", "misc.msg.noon.short", "misc.msg.afternoon.short", "misc.msg.evening.short", "misc.msg.lateatnight.short"};
// the beginning null makes it compatible with the joda int constants.
public final static Month[] months = new Month[]{null, LammaConst.JANUARY, LammaConst.FEBRUARY, LammaConst.MARCH,
LammaConst.APRIL, LammaConst.MAY, LammaConst.JUNE, LammaConst.JULY,
LammaConst.AUGUST, LammaConst.SEPTEMBER, LammaConst.OCTOBER, LammaConst.NOVEMBER, LammaConst.DECEMBER};
public final static Weekday[] weeksdays = new Weekday[]{null, LammaConst.MONDAY, LammaConst.TUESDAY, LammaConst.WEDNESDAY, LammaConst.THURSDAY,
LammaConst.FRIDAY, LammaConst.SATURDAY, LammaConst.SUNDAY};
public static boolean isInFuture(long time) {
return isInFuture(new Date(time));
}
public static boolean isInFuture(Date date) {
return date.after(new Date());
}
/**
* Generates an ArrayList of Dates. Stepping through the day in 15 minutes steps like {"17:00","17:15"...}
* Der verwendete Datentyp ist GregorianCalendar
*/
public static ArrayList<Date> getTimeList() {
ArrayList list = new ArrayList();
GregorianCalendar gc = today();
for (int i = 1; i <= 96; i++) {
list.add(new Date(gc.getTimeInMillis()));
gc.add(GregorianCalendar.MINUTE, 15);
}
return list;
}
public static ListCellRenderer getTimeRenderer() {
return new ListCellRenderer() {
DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
@Override
public Component getListCellRendererComponent(JList jList, Object o, int i, boolean isSelected, boolean cellHasFocus) {
String text;
if (o == null) {
text = SYSTools.xx("misc.commands.>>noselection<<");
} else if (o instanceof Date) {
Date date = (Date) o;
text = timeFormat.format(date) + " " + SYSTools.xx("misc.msg.Time.short");
} else {
text = o.toString();
}
return new DefaultListCellRenderer().getListCellRendererComponent(jList, text, i, isSelected, cellHasFocus);
}
};
}
public static GregorianCalendar toGC(Date d) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(d.getTime());
return gc;
}
public static GregorianCalendar toGC(long l) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(l);
return gc;
}
public static String toGermanTime(GregorianCalendar gc) {
Date date = new Date(gc.getTimeInMillis());
Format formatter;
formatter = new SimpleDateFormat("HH:mm");
return formatter.format(date);
}
/**
* A "sane" birthday is not older than 120 years and not younger than 15 years.
*
* @param date
* @return
*/
public static boolean isBirthdaySane(Date date) {
if (date == null) return false;
//TODO: those min and max values must not be hardcoded in future
int maxage = 120;
int minage = 15;
DateMidnight min = new DateMidnight().minusYears(minage);
DateMidnight max = new DateMidnight().minusYears(maxage);
DateMidnight d = new DateMidnight(date);
return d.isAfter(max) && d.isBefore(min);
}
public static void handleDateFocusLost(FocusEvent evt, DateMidnight min, DateMidnight max) {
DateTime dt;
if (max == null) {
max = new DateMidnight();
}
try {
dt = new DateTime(parseDate(((JTextField) evt.getSource()).getText()));
} catch (NumberFormatException ex) {
OPDE.getDisplayManager().addSubMessage(new DisplayMessage(SYSTools.xx("misc.msg.wrongdate")));
dt = new DateTime();
}
if (dt.isAfter(max)) {
dt = new DateTime();
DisplayMessage dm = new DisplayMessage(dt.isAfterNow() ? SYSTools.xx("misc.msg.futuredate") : SYSTools.xx("misc.msg.wrongdate"));
OPDE.getDisplayManager().addSubMessage(dm);
}
if (dt.isBefore(min)) {
dt = new DateTime();
OPDE.getDisplayManager().addSubMessage(new DisplayMessage(SYSTools.xx("misc.msg.DateTooOld")));
}
((JTextField) evt.getSource()).setText(DateFormat.getDateInstance().format(dt.toDate()));
}
public static void handleDateFocusLost(FocusEvent evt, LocalDate min, LocalDate max) {
LocalDate dt;
if (max == null) {
max = new LocalDate();
}
try {
dt = new LocalDate(parseDate(((JTextField) evt.getSource()).getText()));
} catch (NumberFormatException ex) {
OPDE.getDisplayManager().addSubMessage(new DisplayMessage(SYSTools.xx("misc.msg.wrongdate")));
dt = new LocalDate();
}
if (dt.isAfter(max)) {
dt = new LocalDate();
DisplayMessage dm = new DisplayMessage(dt.isAfter(max) ? SYSTools.xx("misc.msg.futuredate") : SYSTools.xx("misc.msg.wrongdate"));
OPDE.getDisplayManager().addSubMessage(dm);
}
if (dt.isBefore(min)) {
dt = new LocalDate();
OPDE.getDisplayManager().addSubMessage(new DisplayMessage(SYSTools.xx("misc.msg.DateTooOld")));
}
((JTextField) evt.getSource()).setText(DateFormat.getDateInstance().format(dt.toDate()));
}
/**
* Expiry dates usually have a form like "12-10" oder "12/10" to indicate that the product in question is
* best before December 31st, 2010. This method parses dates like this.
* If it fails it hands over the parsing efforts to <code>public static Date parseDate(String input)</code>.
*
* @param input a string to be parsed. It can handle the following formats "mm/yy", "mm/yyyy" (it also recognizes these kinds of
* dates if the slash is replaced with one of the following chars: "-,.".
* @return the parsed date which is always the last day and the last second of that month.
* @throws NumberFormatException
*/
public static DateTime parseExpiryDate(String input) throws NumberFormatException {
if (input == null || input.isEmpty()) {
throw new NumberFormatException("empty");
}
input = input.trim();
if (input.indexOf(".") + input.indexOf(",") + input.indexOf("-") + input.indexOf("/") == -4) {
input += ".";
}
StringTokenizer st = new StringTokenizer(input, "/,.-");
if (st.countTokens() == 1) { // only one number, then this must be the month. we add the current year.
input = "1." + input + SYSCalendar.today().get(GregorianCalendar.YEAR);
}
if (st.countTokens() == 2) { // complete expiry date. we fill up some dummy day.
input = "1." + input;
//st = new StringTokenizer(input, "/,.-"); // split again...
}
DateTime expiry = new DateTime(parseDate(input));
// when the user has entered a complete date, then we return that date
// if he has omitted some parts of it, we consider it always the last day of that month.
return st.countTokens() == 3 ? expiry : expiry.dayOfMonth().withMaximumValue().secondOfDay().withMaximumValue();
}
public static Date parseDate(String input) throws NumberFormatException {
if (input == null || input.equals("")) {
throw new NumberFormatException("empty");
}
if (input.indexOf(".") + input.indexOf(",") + input.indexOf("-") + input.indexOf("/") == -4) {
input += "."; // er war zu faul auch nur einen punkt anzuhängen.
}
StringTokenizer st = new StringTokenizer(input, "/,.-");
if (st.countTokens() == 1) { // Vielleicht fehlen ja nur die Monats- und Jahresangaben. Dann hängen wir sie einach an.
input += (SYSCalendar.today().get(GregorianCalendar.MONTH) + 1) + "." + SYSCalendar.today().get(GregorianCalendar.YEAR);
st = new StringTokenizer(input, "/,.-"); // dann nochmal aufteilen...
}
if (st.countTokens() == 2) { // Vielleicht fehlt ja nur die Jahresangabe. Dann hängen wir es einfach an.
if (!input.trim().substring(input.length() - 1).equals(".") && !input.trim().substring(input.length() - 1).equals(",")) {
input += "."; // er war zu faul den letzten Punkt anzuhängen.
}
input += SYSCalendar.today().get(GregorianCalendar.YEAR);
st = new StringTokenizer(input, "/,.-"); // dann nochmal aufteilen...
}
if (st.countTokens() != 3) {
throw new NumberFormatException("wrong format");
}
String sTag = st.nextToken();
String sMonat = st.nextToken();
String sJahr = st.nextToken();
int tag, monat, jahr;
// Year 2010 Problem
GregorianCalendar now = new GregorianCalendar();
int decade = (now.get(GregorianCalendar.YEAR) / 10) * 10;
int century = (now.get(GregorianCalendar.YEAR) / 100) * 100;
try {
tag = Integer.parseInt(sTag);
} catch (NumberFormatException nfe) {
throw new NumberFormatException("day");
}
try {
monat = Integer.parseInt(sMonat);
} catch (NumberFormatException nfe) {
throw new NumberFormatException("month");
}
try {
jahr = Integer.parseInt(sJahr);
} catch (NumberFormatException nfe) {
throw new NumberFormatException("year");
}
if (jahr < 0) {
throw new NumberFormatException("year");
}
if (jahr > 9999) {
throw new NumberFormatException("year");
}
if (jahr < 10) {
jahr += decade;
}
if (jahr < 100) {
jahr += century;
}
if (monat < 1 || monat > 12) {
throw new NumberFormatException("month");
}
if (tag < 1 || tag > eom(new GregorianCalendar(jahr, monat - 1, 1))) {
throw new NumberFormatException("month");
}
return new DateMidnight(jahr, monat, tag).toDate();
}
/**
* gibt das heutige Datum zurück, allerdings um die Uhrzeitanteile bereinigt.
*
* @return das ein um die Uhrzeit bereinigtes Datum.
*/
public static GregorianCalendar today() {
GregorianCalendar gc = new GregorianCalendar();
gc.set(GregorianCalendar.HOUR, 0);
gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
gc.set(GregorianCalendar.MINUTE, 0);
gc.set(GregorianCalendar.SECOND, 0);
gc.set(GregorianCalendar.MILLISECOND, 0);
return gc;
}
public static long now() {
return java.lang.System.currentTimeMillis();
//return heute().getTimeInMillis();
}
/**
* erkennt Uhrzeitn im Format HH:MM[:SS]
*/
public static GregorianCalendar parseTime(String input) throws NumberFormatException {
return parseTime(input, new GregorianCalendar());
}
/**
* erkennt Uhrzeiten im Format HH:MM und erstellt einen GregorianCalendar basierend auf ref
*/
public static GregorianCalendar parseTime(String input, GregorianCalendar gc)
throws NumberFormatException {
if (input == null || input.equals("")) {
throw new NumberFormatException("leere Eingabe");
}
StringTokenizer st = new StringTokenizer(input, ":,.");
if (st.countTokens() > 3) {
throw new NumberFormatException("falsches Format");
}
String sStunde = "00";
String sMinute = "00";
String sSekunde = "00";
if (st.countTokens() == 1) { // maybe a simple hour
sStunde = st.nextToken();
} else if (st.countTokens() == 2) { // maybe a simple hour
sStunde = st.nextToken();
sMinute = st.nextToken();
} else {
sStunde = st.nextToken();
sMinute = st.nextToken();
sSekunde = st.nextToken();
}
int stunde, minute, sekunde;
GregorianCalendar now = (GregorianCalendar) gc.clone();
try {
stunde = Integer.parseInt(sStunde);
} catch (NumberFormatException nfe) {
throw new NumberFormatException("stunde");
}
try {
minute = Integer.parseInt(sMinute);
} catch (NumberFormatException nfe) {
throw new NumberFormatException("minute");
}
try {
sekunde = Integer.parseInt(sSekunde);
} catch (NumberFormatException nfe) {
throw new NumberFormatException("Sekunde");
}
if (stunde < 0) {
throw new NumberFormatException("stunde");
}
if (stunde > 23) {
throw new NumberFormatException("stunde");
}
if (minute < 0 || minute > 59) {
throw new NumberFormatException("minute");
}
if (sekunde < 0 || sekunde > 59) {
throw new NumberFormatException("Sekunde");
}
now.set(GregorianCalendar.HOUR_OF_DAY, stunde);
now.set(GregorianCalendar.MINUTE, minute);
now.set(GregorianCalendar.SECOND, sekunde);
return now;
}
/**
* @param ts Ist ein TS mit der Uhrzeit, für die wir wissen möchten in welchem Bereich der Medikamenten Vergabe
* sie liegt. Früh morgens, morgens... etc. Das Datum in diesem TS ist egal. Es geht NUR um die Uhrzeit.
* @return Zeit-Konstante gemäß den Angaben in SYSConst.FM ... SYSConst.NA.
*/
public static byte ermittleZeit(long ts) {
byte zeit;
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(ts);
long fm = parseTime(OPDE.getProps().getProperty("FM"), gc).getTimeInMillis();
long mo = parseTime(OPDE.getProps().getProperty("MO"), gc).getTimeInMillis();
long mi = parseTime(OPDE.getProps().getProperty("MI"), gc).getTimeInMillis();
long nm = parseTime(OPDE.getProps().getProperty("NM"), gc).getTimeInMillis();
long ab = parseTime(OPDE.getProps().getProperty("AB"), gc).getTimeInMillis();
long na = parseTime(OPDE.getProps().getProperty("NA"), gc).getTimeInMillis();
if (fm <= ts && ts < mo) {
zeit = SYSConst.FM;
} else if (mo <= ts && ts < mi) {
zeit = SYSConst.MO;
} else if (mi <= ts && ts < nm) {
zeit = SYSConst.MI;
} else if (nm <= ts && ts < ab) {
zeit = SYSConst.NM;
} else if (ab <= ts && ts < na) {
zeit = SYSConst.AB;
} else {
zeit = SYSConst.NA;
}
return zeit;
}
public static byte whatShiftIs(byte timeID) {
byte shift;
if (BYTE_EARLY_IN_THE_MORNING <= timeID && timeID < BYTE_MORNING) {
shift = SHIFT_VERY_EARLY;
} else if (BYTE_MORNING <= timeID && timeID < BYTE_AFTERNOON) {
shift = SHIFT_EARLY;
} else if (BYTE_AFTERNOON <= timeID && timeID < BYTE_LATE_AT_NIGHT) {
shift = SHIFT_LATE;
} else {
shift = SHIFT_VERY_LATE;
}
return shift;
}
public static byte whatShiftIs(Date date) {
// TODO: not clean enough. there should be one method for DFNs and one method for BHPs. even though they may do the same.
return whatShiftIs(whatTimeIDIs(date));
}
/**
* determines to which timeofday code a given date object belongs. The settings in SYSProps are taken into account.
* or in short: it answers a question like "is 0800h early, noon or early in the morning ?"
*
* @param date
* @return timecode
*/
public static byte whatTimeIDIs(Date date) {
byte timeid;
DateTimeFormatter parser = DateTimeFormat.forPattern("HH:mm");
DateTime early_in_the_morning = parser.parseDateTime(OPDE.getProps().getProperty(STRING_EARLY_IN_THE_MORNING));
DateTime morning = parser.parseDateTime(OPDE.getProps().getProperty(STRING_MORNING));
DateTime noon = parser.parseDateTime(OPDE.getProps().getProperty(STRING_NOON));
DateTime afternoon = parser.parseDateTime(OPDE.getProps().getProperty(STRING_AFTERNOON));
DateTime evening = parser.parseDateTime(OPDE.getProps().getProperty(STRING_EVENING));
DateTime late_at_night = parser.parseDateTime(OPDE.getProps().getProperty(STRING_LATE_AT_NIGHT));
Period period_early_in_the_morning = new Period(early_in_the_morning.getHourOfDay(), early_in_the_morning.getMinuteOfHour(), early_in_the_morning.getSecondOfMinute(), early_in_the_morning.getMillisOfSecond());
Period period_morning = new Period(morning.getHourOfDay(), morning.getMinuteOfHour(), morning.getSecondOfMinute(), morning.getMillisOfSecond());
Period period_noon = new Period(noon.getHourOfDay(), noon.getMinuteOfHour(), noon.getSecondOfMinute(), noon.getMillisOfSecond());
Period period_afternoon = new Period(afternoon.getHourOfDay(), afternoon.getMinuteOfHour(), afternoon.getSecondOfMinute(), afternoon.getMillisOfSecond());
Period period_evening = new Period(evening.getHourOfDay(), evening.getMinuteOfHour(), evening.getSecondOfMinute(), evening.getMillisOfSecond());
Period period_late_at_night = new Period(late_at_night.getHourOfDay(), late_at_night.getMinuteOfHour(), late_at_night.getSecondOfMinute(), late_at_night.getMillisOfSecond());
DateTime ref = new DateTime(date);
DateTime eitm = new LocalDate(date).toDateTimeAtStartOfDay().plus(period_early_in_the_morning);
DateTime m = new LocalDate(date).toDateTimeAtStartOfDay().plus(period_morning);
DateTime n = new LocalDate(date).toDateTimeAtStartOfDay().plus(period_noon);
DateTime a = new LocalDate(date).toDateTimeAtStartOfDay().plus(period_afternoon);
DateTime e = new LocalDate(date).toDateTimeAtStartOfDay().plus(period_evening);
DateTime lan = new LocalDate(date).toDateTimeAtStartOfDay().plus(period_late_at_night);
if (eitm.compareTo(ref) <= 0 && ref.compareTo(m) < 0) {
timeid = BYTE_EARLY_IN_THE_MORNING;
} else if (m.compareTo(ref) <= 0 && ref.compareTo(n) < 0) {
timeid = BYTE_MORNING;
} else if (n.compareTo(ref) <= 0 && ref.compareTo(a) < 0) {
timeid = BYTE_NOON;
} else if (a.compareTo(ref) <= 0 && ref.compareTo(e) < 0) {
timeid = BYTE_AFTERNOON;
} else if (e.compareTo(ref) <= 0 && ref.compareTo(lan) < 0) {
timeid = BYTE_EVENING;
} else {
timeid = BYTE_LATE_AT_NIGHT;
}
return timeid;
}
/**
* EndOfMonth
* Berechnet das Enddatum eines Monats, passend zum Parameter
*
* @param d Datum innerhalb des entsprechenden Monats.
* @return Enddatum des Monats
*/
public static Date eom(Date d) {
GregorianCalendar gc = toGC(d);
int ieom = eom(gc);
gc.set(GregorianCalendar.DATE, ieom);
return new Date(endOfDay(new Date(gc.getTimeInMillis())));
}
public static Date bom(Date d) {
GregorianCalendar gc = toGC(d);
gc.set(GregorianCalendar.DATE, 1);
return new Date(startOfDay(new Date(gc.getTimeInMillis())));
}
public static int eom(GregorianCalendar d) {
return d.getActualMaximum(GregorianCalendar.DAY_OF_MONTH);
// switch (d.get(GregorianCalendar.MONTH)) {
// case GregorianCalendar.JANUARY: {
// return 31;
// }
// case GregorianCalendar.FEBRUARY: {
// if (d.isLeapYear(d.get(GregorianCalendar.YEAR))) {
// return 29;
// } else {
// return 28;
// }
// }
// case GregorianCalendar.MARCH: {
// return 31;
// }
// case GregorianCalendar.APRIL: {
// return 30;
// }
// case GregorianCalendar.MAY: {
// return 31;
// }
// case GregorianCalendar.JUNE: {
// return 30;
// }
// case GregorianCalendar.JULY: {
// return 31;
// }
// case GregorianCalendar.AUGUST: {
// return 31;
// }
// case GregorianCalendar.SEPTEMBER: {
// return 30;
// }
// case GregorianCalendar.OCTOBER: {
// return 31;
// }
// case GregorianCalendar.NOVEMBER: {
// return 30;
// }
// case GregorianCalendar.DECEMBER: {
// return 31;
// }
// min
// default: {
// return 0;
// }
// }
} // eom
// /**
// * Entscheidet ob zwei Daten in der selben Woche liegen. Berücksichtigt dabei die Jahreszahlen, so dass KW 34/2006 != KW 34/2005.
// */
// public static int sameWeek(GregorianCalendar a, GregorianCalendar b) {
// NumberFormat form = new java.text.DecimalFormat("00");
//
// int aYear = a.get(GregorianCalendar.YEAR);
// int bYear = b.get(GregorianCalendar.YEAR);
//
// // Die KW der letzten Tage eines Jahres gehören manchmal schon zum neuen Jahr. So gehörte der 29.12.2008 schon zur KW1 von 2009.
// // Diese Zeilen berücksichtigen das. Sie erhöhen die Jahreszahl wenn der Monat Dezember ist und die KW trotzdem 1.
// // Bug 0000016: Fehlende Einträge in der Behandlungspflege
// if (a.get(GregorianCalendar.WEEK_OF_YEAR) == 1 && a.get(GregorianCalendar.MONTH) == GregorianCalendar.DECEMBER) {
// aYear++;
// }
// if (b.get(GregorianCalendar.WEEK_OF_YEAR) == 1 && b.get(GregorianCalendar.MONTH) == GregorianCalendar.DECEMBER) {
// bYear++;
// }
//
// String sa = Integer.toString(aYear) + form.format(a.get(GregorianCalendar.WEEK_OF_YEAR));
// String sb = Integer.toString(bYear) + form.format(b.get(GregorianCalendar.WEEK_OF_YEAR));
// int ia = Integer.parseInt(sa);
// int ib = Integer.parseInt(sb);
//
// if (ia > ib) {
// return 1;
// }
// if (ia < ib) {
// return -1;
// }
// return 0;
// }
//
// /**
// * Entscheidet ob zwei Daten im selben Monat liegen. Berücksichtigt dabei die Jahreszahlen, so dass Monat 12/2006 != Monat 12/2005.
// */
// public static int sameMonth(GregorianCalendar a, GregorianCalendar b) {
// NumberFormat form = new java.text.DecimalFormat("00");
// String sa = Integer.toString(a.get(GregorianCalendar.YEAR)) + form.format(a.get(GregorianCalendar.MONTH));
// String sb = Integer.toString(b.get(GregorianCalendar.YEAR)) + form.format(b.get(GregorianCalendar.MONTH));
// int ia = Integer.parseInt(sa);
// int ib = Integer.parseInt(sb);
//
// if (ia > ib) {
// return 1;
// }
// if (ia < ib) {
// return -1;
// }
// return 0;
// }
// /**
// * Entscheidet ob zwei Daten am selben Tag liegen.
// *
// * @param a Datum a
// * @param b Datum b
// * @return 0, wenn a und b am selben Tag liegen. -1, wenn a <b>vor</b> b ist. und +1 wenn a <b>nach</b> b ist.
// */
// public static int sameDay(GregorianCalendar a, GregorianCalendar b) {
// NumberFormat form = new java.text.DecimalFormat("00");
// String sa = Integer.toString(a.get(GregorianCalendar.YEAR)) + form.format(a.get(GregorianCalendar.MONTH)) + form.format(a.get(GregorianCalendar.DATE));
// String sb = Integer.toString(b.get(GregorianCalendar.YEAR)) + form.format(b.get(GregorianCalendar.MONTH)) + form.format(b.get(GregorianCalendar.DATE));
// int ia = Integer.parseInt(sa);
// int ib = Integer.parseInt(sb);
//
// if (ia > ib) {
// return 1;
// }
// if (ia < ib) {
// return -1;
// }
// return 0;
// }
// /**
// * Entscheidet ob zwei Daten am selben Tag liegen.
// *
// * @param a Datum a
// * @param b Datum b
// * @return 0, wenn a und b am selben Tag liegen. -1, wenn a <b>vor</b> b ist. und +1 wenn a <b>nach</b> b ist.
// */
// public static int sameDay(Date a, Date b) {
// return sameDay(toGC(a), toGC(b));
// }
//
// public static int sameDay(long a, long b) {
// return sameDay(toGC(a), toGC(b));
// }
// public static int calculateAge(GregorianCalendar a, GregorianCalendar b) {
// return getDaysBetween(a, b) / 365;
// }
//
// public static int calculateAge(GregorianCalendar a) {
// return getDaysBetween(a, new GregorianCalendar()) / 365;
// }
public static void checkJDC(JDateChooser jdc) {
if (jdc.getDate() == null) {
jdc.setDate(new Date());
} // ungültiges Datum
if (jdc.getMaxSelectableDate().before(jdc.getDate())) {
jdc.setDate(new Date());
}
}
// public static boolean isJDCValid(JDateChooser jdc) {
// boolean valid = false;
// boolean dateTrouble = (jdc.getDate() == null);
// return !dateTrouble && isInRange(jdc);
// }
/**
* Addiert (bzw. Subtrahiert) eine angebenene Anzahl von Tagen auf das (bzw. von dem)
* übergebenen Datum und gibt es dann zurück.
*
* @param date - Ausgangsdatum
* @param numDays - Anzahl der Tage die addiert bzw. subtrahiert werdenn sollen.
* @return neues Datum
*/
public static Date addDate(Date date, int numDays) {
GregorianCalendar gc = toGC(date);
gc.add(GregorianCalendar.DATE, numDays);
return new Date(gc.getTimeInMillis());
}
// // Das hier ist noch nicht ganz richtig. Vertut sich an den Rändern schon mal.
// public static Date addDate(Date date, int amount, Date min, Date max) {
// GregorianCalendar gc = toGC(date);
// gc.add(GregorianCalendar.DATE, amount);
// Date result = new Date(gc.getTimeInMillis());
// if (!(trimTime(min).before(trimTime(result)) && trimTime(max).after(trimTime(result)))) {
// result = date;
// }
// return result;
// }
// public static Date addField(Date date, int amount, int field) {
// GregorianCalendar gc = toGC(date);
// gc.add(field, amount);
// return new Date(gc.getTimeInMillis());
// }
public static Date min(Date d1, Date d2) {
Date result;
if (d1.before(d2)) {
result = d1;
} else {
result = d2;
}
return result;
}
public static Date max(Date d1, Date d2) {
Date result;
if (d1.before(d2)) {
result = d2;
} else {
result = d1;
}
return result;
}
/*
* Erstellt ein ComboBox Modell, dass eine Liste mit Dates zwischen den Begrenzungs-Zeitpunkten enthält.
*
* @param start Beginn der Liste
* @param end Ende der Liste
*/
public static DefaultComboBoxModel createMonthList(LocalDate start, LocalDate end) {
DefaultComboBoxModel dcbm = new DefaultComboBoxModel();
for (LocalDate month = start; month.compareTo(end) <= 0; month = month.plusMonths(1)) {
dcbm.addElement(month);
}
return dcbm;
}
// /**
// * gibt das heutige Datum zurück, allerdings um die Uhrzeitanteile bereinigt.
// *
// * @return das ein um die Uhrzeit bereinigtes Datum.
// */
// public static GregorianCalendar trimTime(GregorianCalendar gc) {
// gc.set(GregorianCalendar.HOUR, 0);
// gc.set(GregorianCalendar.MINUTE, 0);
// gc.set(GregorianCalendar.SECOND, 0);
// gc.set(GregorianCalendar.MILLISECOND, 0);
// return gc;
// }
/**
* Bereinigt ein Datum um die Uhrzeitanteile, damit die Vergleichsoperatoren richtig funktionieren, wenn man sich nur auf das
* Datum beschränken will.
*
* @param date das zu bereinigende Datum
* @return das bereinigte Datum
*/
// public static Date trimTime(Date date) {
// return new Date(trimTime(toGC(date)).getTimeInMillis());
// }
//
// public static boolean betweenDisjunctive(Date from, Date to, Date date) {
// return date.getTime() > from.getTime() && date.getTime() < to.getTime();
// }
//
// public static boolean betweenOverlap(Date from, Date to, Date date) {
// return betweenDisjunctive(from, to, date) || date.getTime() == from.getTime() || date.getTime() == to.getTime();
// }
//
// public static boolean betweenDisjunctive(Date fromInt, Date toInt, Date from, Date to) {
// return betweenDisjunctive(fromInt, toInt, from) && betweenDisjunctive(fromInt, toInt, to);
// }
//
// public static boolean betweenOverlap(Date fromInt, Date toInt, Date from, Date to) {
// return betweenOverlap(fromInt, toInt, from) && betweenOverlap(fromInt, toInt, to);
// }
//
// public static boolean isInRange(JDateChooser jdc) {
// if (jdc.getDate() != null) {
// return betweenOverlap(jdc.getMinSelectableDate(), jdc.getMaxSelectableDate(), jdc.getDate());
// }
// return false;
// }
//
// public static ArrayList getUhrzeitListe(GregorianCalendar start, GregorianCalendar stop, int minutes) {
// ArrayList result = new ArrayList();
// while (start.before(stop)) {
// result.add(toGermanTime(start));
// start.add(GregorianCalendar.MINUTE, minutes);
// }
// return result;
// }
//
//
// public static Date addTime2Date(Date date, Time time) {
// return new Date(addTime2Date(toGC(date), toGC(time)).getTimeInMillis());
// }
//
// public static DateTime addCurrentTime(DateMidnight date) {
// DateTime time = new DateTime();
//
// return date.toDateTime().withTime(time.getHourOfDay(), time.getMinuteOfHour(), time.getSecondOfMinute(), time.getMillisOfSecond());
// }
//
// public static Date addTime2Date(Date date, Date time) {
// return new Date(addTime2Date(toGC(date), toGC(time)).getTimeInMillis());
// }
/**
* Setzt die Zeitkomponente eines GregorianCalendars. Das heisst ganz einfach,
* wenn man ein Datum hat (in einem GC) und in einem anderen GC steht die Uhrzeit, dann
* fügt diese Methode die beiden Komponenten zu einem Datum und Uhrzeit Wert zusammen
* und gibt diesen zurück.
*
* @param date - Datumsanteil
* @param time - Uhrzeitanzeil
* @return Datum und Uhrzeit kombiniert.
*/
public static GregorianCalendar addTime2Date(GregorianCalendar date, GregorianCalendar time) {
date.set(GregorianCalendar.HOUR_OF_DAY, time.get(GregorianCalendar.HOUR_OF_DAY));
date.set(GregorianCalendar.MINUTE, time.get(GregorianCalendar.MINUTE));
date.set(GregorianCalendar.SECOND, time.get(GregorianCalendar.SECOND));
date.set(GregorianCalendar.MILLISECOND, time.get(GregorianCalendar.MILLISECOND));
return (GregorianCalendar) date.clone();
}
public static GregorianCalendar setDate2Time(GregorianCalendar source, GregorianCalendar target) {
target.set(GregorianCalendar.DATE, source.get(GregorianCalendar.DATE));
target.set(GregorianCalendar.MONTH, source.get(GregorianCalendar.MONTH));
target.set(GregorianCalendar.YEAR, source.get(GregorianCalendar.YEAR));
return (GregorianCalendar) target.clone();
}
/**
* Diese Routine vergleicht Uhrzeiten, die in zwei longs hinterlegt sind.
* Das Besondere dabei ist, dass das Datum ausser acht gelassen wird.
*
* @return int < 0, wenn time1 < time2; int == 0, wenn time1 = time2; int > 0, wenn time1 > time2
* @time1
* @time2
*/
public static int compareTime(long time1, long time2) {
// normalisierung des timestamps
GregorianCalendar gc1 = new GregorianCalendar();
gc1.setTimeInMillis(time1);
GregorianCalendar gc2 = new GregorianCalendar();
gc2.setTimeInMillis(time2);
gc2 = setDate2Time(gc1, gc2); // Hier werden die Daten gleichgesetzt.
return gc1.compareTo(gc2);
}
/**
* Diese Routine vergleicht Uhrzeiten, die in zwei longs hinterlegt sind.
* Das Besondere dabei ist, dass das Datum ausser acht gelassen wird.
*
* @return int < 0, wenn time1 < time2; int == 0, wenn time1 = time2; int > 0, wenn time1 > time2
* @time1
* @time2
*/
public static int compareTime(Date date1, Date date2) {
return compareTime(date1.getTime(), date2.getTime());
}
public static long startOfDay() {
return startOfDay(new Date());
}
/**
* Nimmt den aktuellen Zeitpunkt, setzt die Zeit auf 23:59:59 und gibt das Ergebnis zurück.
*
* @return
*/
public static long endOfDay() {
return endOfDay(new Date());
}
/**
* nimmt das übergebene Datum und setzt die Uhrzeitkomponente auf 23:59:59
*
* @param d
* @return das Ergebnis als TimeInMillis
*/
public static long endOfDay(Date d) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(d.getTime());
gc.set(GregorianCalendar.HOUR_OF_DAY, 23);
gc.set(GregorianCalendar.MINUTE, 59);
gc.set(GregorianCalendar.SECOND, 59);
gc.set(GregorianCalendar.MILLISECOND, 0);
return gc.getTimeInMillis();
}
/**
* nimmt das übergebene Datum und setzt die Uhrzeitkomponente auf 00:00:00.
*
* @param d
* @return das Ergebnis als TimeInMillis
*/
public static long startOfDay(Date d) {
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(d.getTime());
gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
gc.set(GregorianCalendar.MINUTE, 0);
gc.set(GregorianCalendar.SECOND, 0);
gc.set(GregorianCalendar.MILLISECOND, 0);
return gc.getTimeInMillis();
}
// /**
// * nimmt das übergebene Datum und setzt die Uhrzeitkomponente auf 12:00:00
// *
// * @param d
// * @return das Ergebnis als TimeInMillis
// */
// public static long midOfDay(Date d) {
// GregorianCalendar gc = new GregorianCalendar();
// gc.setTimeInMillis(d.getTime());
// gc.set(GregorianCalendar.HOUR_OF_DAY, 12);
// gc.set(GregorianCalendar.MINUTE, 0);
// gc.set(GregorianCalendar.SECOND, 0);
// gc.set(GregorianCalendar.MILLISECOND, 0);
// return gc.getTimeInMillis();
// }
public static DateTime midOfDay() {
return midOfDay(new LocalDate());
}
public static DateTime midOfDay(LocalDate d) {
DateTime dt = d.toDateTimeAtCurrentTime();
return dt.withHourOfDay(12).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0);
}
/**
* Berechnet zu einem gegebenen Jahr den Ostersonntag. Dieser wird als GregorianCalendar zurückgegeben.
* Der Algorhythmus wurde von der Internet-Seite www.th-o.de/kalender.htm entnommen.
* Dort wurde er von Walter Irion beschrieben. Danke, Walter und Thomas.
* <p>
* Ich habe leider nicht die geringste Ahnung, was hier passiert. ;-)
*
* @param year
* @return Das Datum des Ostersonntags in dem angegebene Jahr.
* @THO99
*/
public static GregorianCalendar Ostersonntag(int year) {
int a, b, c, d, e, f, g, h, i, k, l, m, n, p;
a = year % 19;
b = year / 100;
c = year % 100;
d = b / 4;
e = b % 4;
f = (b + 8) / 25;
g = (b - f + 1) / 3;
h = (19 * a + b - d - g + 15) % 30;
i = c / 4;
k = c % 4;
l = (32 + 2 * e + 2 * i - h - k) % 7;
m = (a + 11 * h + 22 * l) / 451;
n = (h + l - 7 * m + 114) / 31;
p = (h + l - 7 * m + 114) % 31;
return new GregorianCalendar(year, n - 1, p + 1);
}
public static GregorianCalendar Aschermittwoch(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, -46);
return gc;
}
public static GregorianCalendar Rosenmontag(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, -48);
return gc;
}
public static GregorianCalendar Weiberfastnacht(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, -52);
return gc;
}
public static GregorianCalendar Ostermontag(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, 1);
return gc;
}
public static GregorianCalendar Karfreitag(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, -2);
return gc;
}
public static GregorianCalendar Pfingstsonntag(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, 49);
return gc;
}
public static GregorianCalendar Pfingstmontag(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, 50);
return gc;
}
public static GregorianCalendar ChristiHimmelfahrt(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, 39);
return gc;
}
public static GregorianCalendar Fronleichnam(int year) {
GregorianCalendar gc = Ostersonntag(year);
gc.add(GregorianCalendar.DAY_OF_MONTH, 60);
return gc;
}
public static String toAnsi(GregorianCalendar gc) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = new Date(gc.getTimeInMillis());
return sdf.format(d);
}
/**
* Sucht alle Feiertage in einem Jahr zusammen.
*
* @return Eine Hashmap, die je das Datum als Zeichenkette der PrinterForm "jjjj-mm-tt" enthält und dazu die Bezeichnung des Feiertags.
*/
public static HashMap<LocalDate, String> getHolidays(int from, int to) {
HashMap<LocalDate, String> hm = new HashMap<LocalDate, String>();
// TODO: i18n
for (int year = from; year <= to; year++) {
// Feste Feiertage
hm.put(new LocalDate(year, 1, 1), "Neujahrstag");
hm.put(new LocalDate(year, 5, 1), "Maifeiertag");
hm.put(new LocalDate(year, 10, 3), "Tag der Einheit");
hm.put(new LocalDate(year, 11, 1), "Allerheiligen");
hm.put(new LocalDate(year, 12, 25), "1. Weihnachtstag");
hm.put(new LocalDate(year, 12, 26), "2. Weihnachtstag");
// Ausnahmsweise Feiertage (Was es alles gibt).
// https://github.com/tloehr/Offene-Pflege.de/issues/70
hm.put(new LocalDate(2017, 10, 31), "Reformationstag"); // aus Anlass des 500-jährigen Jubiläums
// Bewegliche Feiertage
hm.put(new LocalDate(Karfreitag(year)), "Karfreitag");
hm.put(new LocalDate(Ostersonntag(year)), "Ostersonntag");
hm.put(new LocalDate(Ostermontag(year)), "Ostermontag");
hm.put(new LocalDate(ChristiHimmelfahrt(year)), "Christi Himmelfahrt");
hm.put(new LocalDate(Pfingstsonntag(year)), "Pfingstsonntag");
hm.put(new LocalDate(Pfingstmontag(year)), "Pfingstmontag");
hm.put(new LocalDate(Fronleichnam(year)), "Fronleichnam");
}
return hm;
}
public static JPopupMenu getMinutesMenu(int[] mins, final Closure action) {
JPopupMenu timemenu = new JPopupMenu(SYSTools.xx("misc.commands.changeeffort"));
for (int min : mins) {
String title = "";
if (min % 60 == 0) {
title = min / 60 + " " + SYSTools.xx("misc.msg.Hour(s)");
} else {
title = min + " " + SYSTools.xx("misc.msg.Minute(s)");
}
JMenuItem item = new JMenuItem(title);
final int minutes = min;
item.addActionListener(evt -> action.execute(minutes));
timemenu.add(item);
}
return timemenu;
}
public static Color getFGItem(Byte shift) {
if (shift == SHIFT_ON_DEMAND) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_ONDEMAND_FGITEM));
} else if (shift == SHIFT_VERY_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_EARLY_FGITEM));
} else if (shift == SHIFT_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_EARLY_FGITEM));
} else if (shift == SHIFT_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_LATE_FGITEM));
} else if (shift == SHIFT_VERY_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_LATE_FGITEM));
}
return null;
}
public static Color getBGItem(Byte shift) {
if (shift == SHIFT_ON_DEMAND) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_ONDEMAND_BGITEM));
} else if (shift == SHIFT_VERY_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_EARLY_BGITEM));
} else if (shift == SHIFT_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_EARLY_BGITEM));
} else if (shift == SHIFT_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_LATE_BGITEM));
} else if (shift == SHIFT_VERY_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_LATE_BGITEM));
}
return null;
}
public static Color getFGSHIFT(Byte shift) {
if (shift == SHIFT_ON_DEMAND) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_ONDEMAND_FGSHIFT));
} else if (shift == SHIFT_OUTCOMES) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_OUTCOME_FGSHIFT));
} else if (shift == SHIFT_VERY_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_EARLY_FGSHIFT));
} else if (shift == SHIFT_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_EARLY_FGSHIFT));
} else if (shift == SHIFT_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_LATE_FGSHIFT));
} else if (shift == SHIFT_VERY_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_LATE_FGSHIFT));
}
return null;
}
public static Color getBGSHIFT(Byte shift) {
if (shift == SHIFT_ON_DEMAND) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_ONDEMAND_BGSHIFT));
} else if (shift == SHIFT_OUTCOMES) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_OUTCOME_BGSHIFT));
} else if (shift == SHIFT_VERY_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_EARLY_BGSHIFT));
} else if (shift == SHIFT_EARLY) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_EARLY_BGSHIFT));
} else if (shift == SHIFT_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_LATE_BGSHIFT));
} else if (shift == SHIFT_VERY_LATE) {
return GUITools.getColor(OPDE.getProps().getProperty(SYSPropsTools.KEY_VERY_LATE_BGSHIFT));
}
return null;
}
public static DateTime eod(DateTime date) {
return date.hourOfDay().withMaximumValue().minuteOfHour().withMaximumValue().secondOfMinute().withMaximumValue().millisOfSecond().withMaximumValue();
}
public static DateTime eod(LocalDate date) {
return eod(date.toDateTimeAtStartOfDay());
}
public static DateTime bom(DateTime d) {
return d.dayOfMonth().withMinimumValue().hourOfDay().withMinimumValue().minuteOfHour().withMinimumValue().secondOfMinute().withMinimumValue().millisOfSecond().withMinimumValue();
}
public static DateTime eom(DateTime d) {
return d.dayOfMonth().withMaximumValue().hourOfDay().withMaximumValue().minuteOfHour().withMaximumValue().secondOfMinute().withMaximumValue().millisOfSecond().withMaximumValue();
}
public static LocalDate bow(LocalDate d) {
return d.dayOfWeek().withMinimumValue();
}
public static LocalDate eow(LocalDate d) {
return d.dayOfWeek().withMaximumValue();
}
public static DateTime boy(int year) {
return new DateTime(year, 1, 1, 0, 0, 0);
}
public static LocalDate boy(LocalDate year) {
return new LocalDate(year.getYear(), 1, 1);
}
public static DateTime eoy(int year) {
return new DateTime(year, 12, 31, 23, 59, 59);
}
public static LocalDate eoy(LocalDate day) {
return new LocalDate(day.getYear(), 12, 31);
}
/**
* bottom of month
*
* @param d
* @return
*/
public static LocalDate bom(LocalDate d) {
return d.dayOfMonth().withMinimumValue();
}
public static LocalDate eom(LocalDate d) {
return d.dayOfMonth().withMaximumValue();
}
public static LocalDate min(LocalDate a, LocalDate b) {
return new LocalDate(Math.min(a.toDateTimeAtStartOfDay().getMillis(), b.toDateTimeAtStartOfDay().getMillis()));
}
public static DateTime max(DateTime a, DateTime b) {
return a.compareTo(b) > 0 ? a : b;
}
public static DateTime min(DateTime a, DateTime b) {
return a.compareTo(b) < 0 ? a : b;
}
public static LocalDate max(LocalDate a, LocalDate b) {
return new LocalDate(Math.max(a.toDateTimeAtStartOfDay().getMillis(), b.toDateTimeAtStartOfDay().getMillis()));
}
public static io.lamma.Date toLammaDate(java.util.Date in) {
LocalDate ld = new LocalDate(in);
return new io.lamma.Date(ld.getYear(), ld.getMonthOfYear(), ld.getDayOfMonth());
}
public static LocalDate toLocalDate(io.lamma.Date in) {
return new LocalDate(in.yyyy(), in.mm(), in.dd());
}
}