[JAVA] Iedere weekdag tussen 2 datums bepalen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • F e r o x
  • Registratie: Mei 2006
  • Laatst online: 18-11-2024
Ik wil in Java iedere bepaalde weekdag tussen 2 datums bepalen. Ik heb bijvoorbeeld de datum 20 april en de datum 30 april. Nu zou ik graag iedere woensdag tussen deze 2 datums bepalen (datum inclusief). Als resultaat is dit dus 21 april en 28 april.

Mijn 2 datums zijn een Date-object. Ik heb ook een Calendar waarmee ik nu al de hele tijd probeer een oplossing te zoeken, maar ik kom er maar niet. Iemand met raad?

Acties:
  • 0 Henk 'm!

  • eghie
  • Registratie: Februari 2002
  • Niet online

eghie

Spoken words!

Wat bedoel jij met "bepalen"?

Acties:
  • 0 Henk 'm!

  • HMS
  • Registratie: Januari 2004
  • Laatst online: 21-08 23:06

HMS

Gewoon 2 calendars maken en daar door lussen en dan checken op is woensdag?

Acties:
  • 0 Henk 'm!

  • Standeman
  • Registratie: November 2000
  • Nu online

Standeman

Prutser 1e klasse

Kijk inderdaad eens goed naar methods van Calendar. Vooral naar cal.set en cal.get :)

The ships hung in the sky in much the same way that bricks don’t.


Acties:
  • 0 Henk 'm!

  • bille
  • Registratie: Mei 2000
  • Laatst online: 16-08 14:37

bille

Don't call me Buff

Probeer eens zoiets als dit:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
Calendar cal = Calendar.getInstance();
cal.set(2010, 4, 21);
Calendar to = Calendar.getInstance();
to.set(2010, 4, 30);
Set<Calendar> wednesdays = new TreeSet<Calendar>();
while (cal.before(to) || cal.equals(to)) {
    
    if(cal.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
        wednesdays.add(cal.clone());
    }
    cal.roll(Calendar.DATE, true);
}


TreeSet is std ordered dus als je een iterator opvraagt krijg je de dates op volgorde van natural ordening terug.

[ Voor 0% gewijzigd door bille op 21-04-2010 18:49 . Reden: zo beter? ]

Ultra Pilammo 6666Mhz AMD, 4251Mbit/s RAM, Gefors V6666 MegaTurbo, 43" TFS, Ultra 80Gig Firewire netwerkkaart en 5D geluid met 66 speakers in 5 dimensies


Acties:
  • 0 Henk 'm!

  • F e r o x
  • Registratie: Mei 2006
  • Laatst online: 18-11-2024
HMS schreef op woensdag 21 april 2010 @ 17:17:
Gewoon 2 calendars maken en daar door lussen en dan checken op is woensdag?
Met een lus lukt het inderdaad zoiezo. Maar er moet toch een 'propere' manier bestaan zonder over alle dagen te moeten itereren?
Gewoon iedere woensdag tussen de 2 data teruggeven als een Date-object. Bijvoorbeeld als resultaat dan een ArrayList<Date>.

Acties:
  • 0 Henk 'm!

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 17-09 12:49

Nick_S

++?????++ Out of Cheese Error

bille schreef op woensdag 21 april 2010 @ 17:57:
Probeer eens zoiets als dit:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
Calendar cal = Calendar.getInstance();
cal.set(2010, 4, 21);
Calendar to = Calendar.getInstance();
to.set(2010, 4, 30);
Set<Calendar> wednesdays = new TreeSet<Calendar>();
while (cal.before(to) || cal.equals(to)) {
    
    if(cal.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
        wednesdays.add(cal);
    }
    cal.roll(Calendar.DATE, true);
}


TreeSet is std ordered dus als je een iterator opvraagt krijg je de dates op volgorde van natural ordening terug.
Aangezien Calendar en Data helaas mutable zijn ga je met deze oplossing een treeset vullen met Calendars die allemaal hetzelfde aangeven, aangezien het ook dezelfde zijn. (Of, als TreeSet geen dubbele ondersteund, een TreeSet met 1 Calendar object.) Je bent hiermee wel op de goede weg, maar ik vind zelf Joda Time lekkerder werken, maar ik weet niet zeker of deze al util functies hiervoor heeft ingebouwd.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Zoek het dagnummer van de startdatum (0-6 dus) en reken daarmee de eerstvolgende woensdag uit. Bereken daarna het aantal weken tussen eerstvolgendewoensdag en einddatum et voila. Als je dus kunt volstaan met enkel het aantal onkom je zelfs an lussen.

Als je alle woensdagen wil hebben neem je de eerstvolgendewoensdag om een lus te beginnen, en while (currentdatum < einddatum) currentdatum.addDays(7) en die voeg je toe aan een list/array/whatever. Dan ontkom je niet aan lussen maar hoef je natuurlijk ook niet elke dag "af te gaan tasten" en kun je per 7 dagen (week) door de range raggen.

Even een snel opzetje gemaakt:

C#:
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
        static void Main(string[] args)
        {
            DateTime start = DateTime.Now.Date;
            DateTime end = new DateTime(2010, 5, 30);

            Console.WriteLine("Number of wednesdays between {0} and {1}: {2}", start, end, CalcDays(start, end, DayOfWeek.Wednesday));
            
            Console.WriteLine("All tuesdays between {0} and {1}:", start, end);
            foreach (DateTime d in GetDaysList(start, end, DayOfWeek.Tuesday))
                Console.WriteLine(d);
        }

        /// <param name="start">The start of the range</param>
        /// <param name="end">The end of the range</param>
        /// <param name="day">The weekday to count</param>
        /// <returns>Returns the number of times the specified weekday occurs between start and end date (inclusive!)</returns>
        private static int CalcDays(DateTime start, DateTime end, DayOfWeek day)
        {
            DateTime firstdate = start.AddDays((int)((int)day - (int)start.DayOfWeek + 7) % 7);
            return (int)Math.Ceiling((end - firstdate).TotalDays / 7) + (end.DayOfWeek == day ? 1 : 0);
        }

        /// <param name="start">The start of the range</param>
        /// <param name="end">The end of the range</param>
        /// <param name="day">The weekdays to return in the list</param>
        /// <returns>Returns a list of dates of a specified day of week between a start and end date (inclusive!)</returns>
        private static List<DateTime> GetDaysList(DateTime start, DateTime end, DayOfWeek day)
        {
            List<DateTime> results = new List<DateTime>();
            DateTime current = start.AddDays((int)((int)day - (int)start.DayOfWeek + 7) % 7);
            while (current < end)
            {
                results.Add(current);
                current = current.AddDays(7);
            }
            return results;
        }

Output:
Number of wednesdays between 21-4-2010 and 30-5-2010: 6
All tuesdays between 21-4-2010 and 30-5-2010:
27-4-2010
4-5-2010
11-5-2010
18-5-2010
25-5-2010

[ Voor 77% gewijzigd door RobIII op 21-04-2010 19:24 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • bille
  • Registratie: Mei 2000
  • Laatst online: 16-08 14:37

bille

Don't call me Buff

Nick_S schreef op woensdag 21 april 2010 @ 18:22:
[...]

Aangezien Calendar en Data helaas mutable zijn ga je met deze oplossing een treeset vullen met Calendars die allemaal hetzelfde aangeven, aangezien het ook dezelfde zijn. (Of, als TreeSet geen dubbele ondersteund, een TreeSet met 1 Calendar object.) Je bent hiermee wel op de goede weg, maar ik vind zelf Joda Time lekkerder werken, maar ik weet niet zeker of deze al util functies hiervoor heeft ingebouwd.
whoopsie true, uit de losse pols en niet getest 8)7 , gooi er een clone() tussen en dan zou die et wel moeten doen. My bad.

Het idee met een increment van 7 dagen na het vinden van de eerste woensdag vond ik wel goed:

Java:
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
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Set;
import java.util.TreeSet;

public class CalTest {

    private static final DateFormat df = new SimpleDateFormat("dd-MM-yyyy");

    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.set(2010, 3, 1);
        Calendar to = Calendar.getInstance();
        to.set(2010, 4, 30);
        // start met een roll van 1 dag
        int rollBy = 1;
        Set<Calendar> wednesdays = new TreeSet<Calendar>();
        while (cal.compareTo(to) < 1) {

            if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
                wednesdays.add((Calendar) cal.clone());
                // als na het vinden van de eerst volgende woensdag wordt het
                // increment verhoogd naar 1 week
                if (rollBy == 1) {
                    rollBy = 7;
                }
            }
            // add ipv roll omdat roll de bovenliggende dagen niet zal verhogen
            cal.add(Calendar.DATE, rollBy);
        }

        for (Calendar d : wednesdays) {
            System.out.println(df.format(d.getTime()));
        }
    }
}


result:
07-04-2010
14-04-2010
21-04-2010
28-04-2010
05-05-2010
12-05-2010
19-05-2010
26-05-2010

[ Voor 60% gewijzigd door bille op 21-04-2010 21:32 ]

Ultra Pilammo 6666Mhz AMD, 4251Mbit/s RAM, Gefors V6666 MegaTurbo, 43" TFS, Ultra 80Gig Firewire netwerkkaart en 5D geluid met 66 speakers in 5 dimensies


Acties:
  • 0 Henk 'm!

  • Nick_S
  • Registratie: Juni 2003
  • Laatst online: 17-09 12:49

Nick_S

++?????++ Out of Cheese Error

bille schreef op woensdag 21 april 2010 @ 18:43:
[...]

Java:
1
2
    private static final DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
}
Bij deze regel gaan mijn nekharen altijd omhoog staan, alle alarmbellen af en nog wat toeters en bellen. (Een keer gebeten na productiegang. Het is persoonlijk. ;))

Iemand bij Sun heeft waarschijnlijk een keer zitten slapen, maar SimpleDateFormat is niet thread safe! Voor dit voorbeeld maakt het niets uit (en waarschijnlijk meestal niet), maar daar kunnen hele nasty bugs uit voortkomen.

Hou een dateformat dus altijd lokaal in een functie, of maak hem thread local als je performance problemen krijgt.

'Nae King! Nae quin! Nae Laird! Nae master! We willna' be fooled agin!'


Acties:
  • 0 Henk 'm!

  • F e r o x
  • Registratie: Mei 2006
  • Laatst online: 18-11-2024
Bedankt al allemaal voor de hulp!

Zal de voorgestelde manieren bekijken om een zo goed mogelijke oplossing te maken.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
F e r o x schreef op donderdag 22 april 2010 @ 00:06:
Zal de voorgestelde manieren bekijken om een zo goed mogelijke oplossing te maken.
Skip even de oplossingen waarin een treeset gebruikt wordt, dat is nl. complete onzin.

Calendar geeft je methoden om iedere keer een dag toe te voegen. Om alle valid dagen te bepalen tussen datum X en Y loop je gewoon net zo lang tot X gelijk is aan Y. Als je tussendoor test of die dag een woensdag, heb je de functionaliteit die je nodig hebt. Heb je absoluut geen treeset (met z'n dure inserts) voor nodig om het resultaat te sorteren want als je van X naar Y itereert (ervanuitgaande dat X < Y) heb je je volgorde al.

[ Voor 106% gewijzigd door Hydra op 23-04-2010 11:48 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Hydra schreef op vrijdag 23 april 2010 @ 11:45:
[...]
Calendar geeft je methoden om iedere keer een dag toe te voegen. Om alle valid dagen te bepalen tussen datum X en Y loop je gewoon net zo lang tot X gelijk is aan Y. Als je tussendoor test of die dag een woensdag, heb je de functionaliteit die je nodig hebt. Heb je absoluut geen treeset (met z'n dure inserts) voor nodig om het resultaat te sorteren want als je van X naar Y itereert (ervanuitgaande dat X < Y) heb je je volgorde al.
Dat kan veel slimmer (althans, met C#, ik weet niet hoe het Calendar ding werkt onder Java).

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
RobIII schreef op vrijdag 23 april 2010 @ 11:56:
Dat kan veel slimmer (althans, met C#, ik weet niet hoe het Calendar ding werkt onder Java).
Je kunt idd vanaf de eerste woensdag iedere keer met 7 ophogen, maar hij zocht maar naar 1 woensdag. Daarnaast is het de vraag of een dergelijke optimalisatie nut gaat hebben als je de snelheid af gaat zetten tegen het extra stukje complexiteit in de code.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Hydra schreef op vrijdag 23 april 2010 @ 12:01:
Je kunt idd vanaf de eerste woensdag iedere keer met 7 ophogen, maar hij zocht maar naar 1 woensdag.
Nee, hij zoekt iedere woensdag tussen 2 datums:
F e r o x schreef op woensdag 21 april 2010 @ 16:58:
Ik wil in Java iedere bepaalde weekdag tussen 2 datums bepalen.
Hydra schreef op vrijdag 23 april 2010 @ 12:01:
Daarnaast is het de vraag of een dergelijke optimalisatie nut gaat hebben als je de snelheid af gaat zetten tegen het extra stukje complexiteit in de code.
Extra stukje complexiteit? Eerste woensdag bepalen en er dan met stappen van een week door heen raggen is nog altijd sneller dan dag voor dag mét een if-statement. Daarbij is het bij grote bereiken tussen start en eind (zeg 1-1-1208 t/m 31-12-2650 bij wijze van) al 7x sneller alleen al omdat je niet dag-voor-dag door de range stapt.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
RobIII schreef op vrijdag 23 april 2010 @ 12:10:
Extra stukje complexiteit? Eerste woensdag bepalen en er dan met stappen van een week door heen raggen is nog altijd sneller dan dag voor dag mét een if-statement. Daarbij is het bij grote bereiken tussen start en eind (zeg 1-1-1208 t/m 31-12-2650 bij wijze van) al 7x sneller alleen al omdat je niet dag-voor-dag door de range stapt.
Ik zeg niet dat het een slecht idee is en ontken niet dat 't sneller gaat zijn. Het is idd een slimmere oplossing maar als je een straightforward probleem is, is het vaak overkill. Als hij van alleen een periode van 1-2 weken wil bepalen waar de woensdagen zitten is het gewoon niet nodig. Daar ging het om. Hij gaf zelf een voorbeeld van tussen 20 en 30 april, daar zitten max 2 woensdagen in vermoed ik zo :)

[ Voor 6% gewijzigd door Hydra op 23-04-2010 12:49 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
RobIII schreef op vrijdag 23 april 2010 @ 11:56:
[...]

Dat kan veel slimmer (althans, met C#, ik weet niet hoe het Calendar ding werkt onder Java).
In c# had ik dit overigens zo gedaan:
C#:
1
2
3
4
5
6
7
8
9
10
        private static IEnumerable<DateTime> GetDaysList(DateTime start, DateTime end,
            DayOfWeek day)
        {
            DateTime dt = start.AddDays((day - start.DayOfWeek + 7) % 7);
            while (dt <= end)
            {
                yield return dt;
                dt = dt.AddDays(7);
            }
        }

(overigens kan 'for' dus ook, maar lijkt me minder duidelijk) In java denk ik zoiets:
Java:
1
2
3
4
5
6
7
8
9
10
11
    private static List<Calendar> GetDaysList(Calendar start, Calendar end,
            int day) {
        List<Calendar> result = new ArrayList<Calendar>();
        Calendar c = ((Calendar) start.clone());
        c.add(Calendar.DATE, (day - c.get(Calendar.DAY_OF_WEEK) + 7) % 7);
        while (c.compareTo(end) < 1) {
            result.add((Calendar) c.clone());
            c.add(Calendar.DATE, 7);
        }
        return result;
    }

of, om hetzelfde resultaat te krijgen:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    private static Iterable<Calendar> GetDaysList(Calendar start,
            Calendar end, int day) {
        final Calendar c = (Calendar) start.clone();
        c.add(Calendar.DATE, (day - c.get(Calendar.DAY_OF_WEEK) + 7) % 7);
        final Calendar to = ((Calendar) end.clone());
        return new Iterable<Calendar>() {
            public Iterator<Calendar> iterator() {
                return new Iterator<Calendar>() {
                    public boolean hasNext() {
                        return c.compareTo(to) < 1;
                    }
                    public Calendar next() {
                        Calendar result = (Calendar) c.clone();
                        c.add(Calendar.DATE, 7);
                        return result;
                    }
                    public void remove() {
                    }
                };
            }
        };
    }

offtopic:
Misschien dat iemand doorheeft waarom ik liever in c# programmeer, of zie ik iets over het hoofd? :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
pedorus schreef op vrijdag 23 april 2010 @ 13:38:
[...]

In c# had ik dit overigens zo gedaan:
Eensch; die yield zou ik ook gebruikt hebben maar vond ik voor 't voorbeeld even niet zo duidelijk (en ik wist niet of iets dergelijks ook in Java kan; daar doe ik zelden iets mee). Sowieso wat 't maar een opzetje; voor zover getest in 3 kleine testjes werkt het maar of 't helemaal bugvrij is heb ik niet getest. Het berekenen van de start dag kan bijvoorbeeld volgens mij nog veel efficiënter maar ik ben nu te duf om daar over na te denken...
* RobIII weer z'n werk in duikt...

[ Voor 32% gewijzigd door RobIII op 23-04-2010 13:50 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1