Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Super fast DateMath class (days_between & day_of_week)  (Read 1941 times)
0 Members and 1 Guest are viewing this topic.
Online Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Posted 2010-05-21 17:09:54 »

I wrote this code because I needed something much faster than java.util.Calendar

Benchmark showing factor 25 higher performance
Running 100 * (for all days between 1970 and 2010)
 DAY_OF_WEEK of Calendar: 1658ms
 DAY_OF_WEEK of DateMath: 67ms


Usage:
1  
2  
int dow  = dayOfWeek(int year, int month, int date)
int days = duration(int fromYear, int fromMonth, int fromDate, int untilYear, int untilMonth, int untilDate)


Sourcecode
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  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
public class DateMath
{
   /**
    * duration(2000/01/01 => 2000/01/01) = 1 days<br>
    * duration(2000/01/01 => 2000/01/03) = 3 days<br>
    * duration(2000/01/03 => 2000/01/01) = [exception]<br>
    */


   public static int duration(int fromYear, int fromMonth, int fromDate, int untilYear, int untilMonth, int untilDate)
   {
      int diff = compare(fromYear, fromMonth, fromDate, untilYear, untilMonth, untilDate);
      if (diff < 0)
         throw new IllegalStateException("from > until");
      return diff + 1;
   }

   /**
    * compare(2000/01/01 => 2000/01/01) = 0<br>
    * compare(2000/01/01 => 2000/01/03) = +2<br>
    * compare(2000/01/03 => 2000/01/01) = -2<br>
    */


   public static int compare(int fromYear, int fromMonth, int fromDate, int untilYear, int untilMonth, int untilDate)
   {
      int from = daysSinceEpoch(fromYear, fromMonth, fromDate);
      int until = daysSinceEpoch(untilYear, untilMonth, untilDate);
      return until - from;
   }

   /**
    * Sunday = 0<br>
    * Monday = 1<br>
    * Tuesday = 2<br>
    * Wednesday = 3<br>
    * Thursday = 4<br>
    * Friday = 5<br>
    * Saturday = 6
    */


   public static int dayOfWeek(int year, int month, int date)
   {
      return (dayOfWeekOnEpoch() + daysSinceEpoch(year, month, date)) % 7;
   }

   /**
    * Range: 1..{365|366}
    */


   public static int getDayInYear(int year, int month, int date)
   {
      if (month < 3)
         return date + (month - 1) * 31;
      date += daysInFebruary(year);
      date += (month - 2) * 30;
      date += (month + (month >> 3)) >> 1;
      return date;
   }

   public static int daysInMonth(int year, int month)
   {
      if (month == 2)
         return daysInFebruary(year);
      return 30 + ((month & 1) ^ (month >> 3));
   }

   public static boolean isLeapDay(int year, int month, int date)
   {
      return (month != 2 || date != 29) ? false : isLeapYear(year);
   }

   public static boolean isLeapYear(int year)
   {
      if (year % 100 == 0)
         return (year % 400 == 0);
      return ((year & 3) == 0);
   }

   private static int daysInFebruary(int year)
   {
      return isLeapYear(year) ? 29 : 28;
   }

   private static int dayOfWeekOnEpoch()
   {
      // 1970/01/01 is a Thursday, 4 days after Sunday
      return 4; //Calendar.THURSDAY - Calendar.SUNDAY;
   }

   private static int daysSinceEpoch(int year, int month, int date)
   {
      int epochLeapDays = getLeapDaysInEpoch();
      int crrntLeapDays = getLeapDaysInYear(year);
      int daysInYearsBetween = 365 * (year - 1970);
      daysInYearsBetween += crrntLeapDays - epochLeapDays;
      daysInYearsBetween += getDayInYear(year, month, date);
      return daysInYearsBetween - 1;
   }

   private static int getLeapDaysInYear(int year)
   {
      return (year / 4) - (year / 100) + (year / 400);
   }

   private static int getLeapDaysInEpoch()
   {
      // final int year = 1970;
      // return (year / 4) - (year / 100) + (year / 400);
      // return 492 - 19 + 4;
      // return 477;
      return 477;
   }
}


Verification code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
         for (int year = 1970; year <= 2010; year++)
         {
            for (int month = 1; month <= 12; month++)
            {
               int daysInMonth = DateMath.daysInMonth(year, month);

               for (int date = 1; date <= daysInMonth; date++)
               {
                  current.set(year, month - 1, date);

                  // check for invalid date
                  if (current.get(Calendar.YEAR) != year) throw new IllegalStateException();
                  if (current.get(Calendar.MONTH) != month - 1) throw new IllegalStateException();
                  if (current.get(Calendar.DATE) != date) throw new IllegalStateException();

                  // check for different results
                  int a = current.get(Calendar.DAY_OF_WEEK);
                  int b = DateMath.dayOfWeek(year, month, date) + Calendar.SUNDAY;
                  if (a != b) throw new IllegalStateException();
               }
            }
         }

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Online Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2010-05-21 17:12:00 »

Benchmark code:
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  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
   public static void benchmark()
   {
      Calendar current = Calendar.getInstance();

      final int runs = 4;
      final int loops = 100;
      int opt1 = 1337;
      int opt2 = 1337;

      for (int i = 0; i < runs; i++)
      {
         // verify results
         for (int year = 1970; year <= 2010; year++)
         {
            for (int month = 1; month <= 12; month++)
            {
               int daysInMonth = DateMath.daysInMonth(year, month);
               for (int date = 1; date <= daysInMonth; date++)
               {
                  current.set(year, month - 1, date);
                  if (current.get(Calendar.YEAR) != year)
                     throw new IllegalStateException();
                  if (current.get(Calendar.MONTH) != month - 1)
                     throw new IllegalStateException();
                  if (current.get(Calendar.DATE) != date)
                     throw new IllegalStateException();

                  opt1 = current.get(Calendar.DAY_OF_WEEK);
                  opt2 = DateMath.dayOfWeek(year, month, date) + Calendar.SUNDAY;
                  if (opt1 != opt2)
                     throw new IllegalStateException(year + "/" + month + "/" + date + " => " + opt1 + " <> " + opt2);
               }
            }
         }
         long t0 = System.nanoTime();
         for (int k = 0; k < loops; k++) // benchmark Calendar
         {
            for (int year = 1970; year <= 2010; year++)
            {
               for (int month = 1; month <= 12; month++)
               {
                  int daysInMonth = DateMath.daysInMonth(year, month);
                  for (int date = 1; date <= daysInMonth; date++)
                  {
                     current.set(year, month - 1, date);
                     opt1 += current.get(Calendar.DAY_OF_WEEK);
                  }
               }
            }
         }
         long t1 = System.nanoTime();
         for (int k = 0; k < loops; k++) // benchmark DateMath
         {
            for (int year = 1970; year <= 2010; year++)
            {
               for (int month = 1; month <= 12; month++)
               {
                  int daysInMonth = DateMath.daysInMonth(year, month);
                  for (int date = 1; date <= daysInMonth; date++)
                  {
                     opt2 += DateMath.dayOfWeek(year, month, date) + Calendar.SUNDAY;
                  }
               }
            }
         }
         long t2 = System.nanoTime();
         System.out.println("Calendar: " + (t1 - t0) / 1000000 + "ms, DateMath: " + (t2 - t1) / 1000000 + "ms");
      }
      System.out.println("prevent opt1 by HotSpot ~~ " + opt1);
      System.out.println("prevent opt2 by HotSpot ~~ " + opt2);
   }

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #2 - Posted 2010-05-21 20:16:21 »

Usage:
1  
int dow  = dayOfWeek(int year, int month, int date)

OMG!

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
int dow  = dayOfWeek(2010, 5, 22);

if (dow > currentDow)
{
    this.BUYBUYBUY();
}
else
{
    this.SELLSELLSELL();
}


BRILLIANT, RIVEN, BRILLIANT! I CAN'T BEIEVE YOU CRACKED THE DOW JONES INDUSTRIAL AVERAGE.

/endJoking

This class will be mighty useful, I've been annoyed with Java's Calendar in the past.

See my work:
OTC Software
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2010-05-21 20:28:23 »

OMG!
True.

This class will be mighty useful, I've been annoyed with Java's Calendar in the past.
Calendar isn't really that bad, it's just plain slow.

Calendar c = Calendar.getInstance();
c.setTime(year, month-1, date);
int dow = c.get(Calendar.DAY_OF_WEEK);




On a side note:
I made a physical copy of your code and have sent it to the authorities.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (38 views)
2014-10-17 03:59:02

Norakomi (29 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (28 views)
2014-10-15 16:18:58

TehJavaDev (56 views)
2014-10-14 00:39:48

TehJavaDev (55 views)
2014-10-14 00:35:47

TehJavaDev (46 views)
2014-10-14 00:32:37

BurntPizza (64 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (78 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!