← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 16759: various calendar/analytics updates, add isIso8601() to calendar, used to skip any kind of convert...

 

------------------------------------------------------------
revno: 16759
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Sun 2014-09-21 14:49:12 +0700
message:
  various calendar/analytics updates, add isIso8601() to calendar, used to skip any kind of converting in analytics, also used to set iso8601 flag in DateTimeUnit
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java
  dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java	2014-08-29 15:45:21 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/AbstractCalendar.java	2014-09-21 07:49:12 +0000
@@ -249,4 +249,10 @@
 
         return DEFAULT_I18N_DAY_SHORT_NAMES[day - 1];
     }
+
+    @Override
+    public boolean isIso8601()
+    {
+        return false;
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java	2014-08-29 10:02:21 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/Calendar.java	2014-09-21 07:49:12 +0000
@@ -73,7 +73,7 @@
     /**
      * Formats dateUnit using supplied date format
      *
-     * @param dateFormat Date format to use
+     * @param dateFormat   Date format to use
      * @param dateTimeUnit DateUnit representing local year, month, day
      * @return Default date format
      * @see #getDateFormat()
@@ -142,9 +142,9 @@
      * Gets interval of type based on DateUnit
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param type     Interval type to get
-     * @param offset   Offset to start at, can be negative of positive
-     * @param length   How many periods to asks for, i.e. type = MONTH, length = 2, two months
+     * @param type         Interval type to get
+     * @param offset       Offset to start at, can be negative of positive
+     * @param length       How many periods to asks for, i.e. type = MONTH, length = 2, two months
      * @return Interval for interval type based on dateUnit
      * @see DateIntervalType
      */
@@ -154,7 +154,7 @@
      * Gets interval of type based on DateUnit using default options, 0 for offset, 1 for length
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param type     Interval type to get
+     * @param type         Interval type to get
      * @return Interval for interval type based on dateUnit
      * @see DateIntervalType
      */
@@ -184,10 +184,10 @@
      * Gets interval of type based on DateUnit
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param type     Interval type to get
-     * @param offset   Offset to start at, can be negative of positive
-     * @param length   How many periods to asks for, i.e. type = MONTH, length = 2, two months
-     * @param periods  How many periods to generate
+     * @param type         Interval type to get
+     * @param offset       Offset to start at, can be negative of positive
+     * @param length       How many periods to asks for, i.e. type = MONTH, length = 2, two months
+     * @param periods      How many periods to generate
      * @return Interval for interval type based on dateUnit
      * @see DateIntervalType
      */
@@ -316,7 +316,7 @@
      * Returns a new dateUnit with specified number of days added
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param days     Days to add
+     * @param days         Days to add
      * @return dateUnit + days
      */
     DateTimeUnit plusDays( DateTimeUnit dateTimeUnit, int days );
@@ -325,7 +325,7 @@
      * Returns a new dateUnit with specified number of days subtracted
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param days     Days to subtract
+     * @param days         Days to subtract
      * @return dateUnit - days
      */
     DateTimeUnit minusDays( DateTimeUnit dateTimeUnit, int days );
@@ -334,7 +334,7 @@
      * Returns a new dateUnit with specified number of weeks added
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param weeks    Weeks to add
+     * @param weeks        Weeks to add
      * @return dateUnit + weeks
      */
     DateTimeUnit plusWeeks( DateTimeUnit dateTimeUnit, int weeks );
@@ -343,7 +343,7 @@
      * Returns a new dateUnit with specified number of weeks subtracted
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param weeks    Weeks to subtract
+     * @param weeks        Weeks to subtract
      * @return dateUnit - weeks
      */
     DateTimeUnit minusWeeks( DateTimeUnit dateTimeUnit, int weeks );
@@ -352,7 +352,7 @@
      * Returns a new dateUnit with specified number of months added
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param months   Months to add
+     * @param months       Months to add
      * @return dateUnit + months
      */
     DateTimeUnit plusMonths( DateTimeUnit dateTimeUnit, int months );
@@ -361,7 +361,7 @@
      * Returns a new dateUnit with specified number of months subtracted
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param months   Months to subtract
+     * @param months       Months to subtract
      * @return dateUnit - months
      */
     DateTimeUnit minusMonths( DateTimeUnit dateTimeUnit, int months );
@@ -370,7 +370,7 @@
      * Returns a new dateUnit with specified number of years added
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param years    Years to add
+     * @param years        Years to add
      * @return dateUnit + years
      */
     DateTimeUnit plusYears( DateTimeUnit dateTimeUnit, int years );
@@ -379,8 +379,15 @@
      * Returns a new dateUnit with specified number of years subtracted
      *
      * @param dateTimeUnit DateUnit representing local year, month, day
-     * @param years    Years to subtract
+     * @param years        Years to subtract
      * @return dateUnit - years
      */
     DateTimeUnit minusYears( DateTimeUnit dateTimeUnit, int years );
+
+    /**
+     * Is this calendar based on ISO 8601 (Iso8601 / Gregorian)
+     *
+     * @return is iso8601 based
+     */
+    boolean isIso8601();
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java	2014-09-01 06:16:29 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/ChronologyBasedCalendar.java	2014-09-21 07:49:12 +0000
@@ -253,55 +253,55 @@
     public DateTimeUnit plusDays( DateTimeUnit dateTimeUnit, int days )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.plusDays( days ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.plusDays( days ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit minusDays( DateTimeUnit dateTimeUnit, int days )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.minusDays( days ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.minusDays( days ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit plusWeeks( DateTimeUnit dateTimeUnit, int weeks )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.plusWeeks( weeks ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.plusWeeks( weeks ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit minusWeeks( DateTimeUnit dateTimeUnit, int weeks )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.minusWeeks( weeks ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.minusWeeks( weeks ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit plusMonths( DateTimeUnit dateTimeUnit, int months )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.plusMonths( months ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.plusMonths( months ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit minusMonths( DateTimeUnit dateTimeUnit, int months )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.minusMonths( months ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.minusMonths( months ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit plusYears( DateTimeUnit dateTimeUnit, int years )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.plusYears( years ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.plusYears( years ), dateTimeUnit.isIso8601() );
     }
 
     @Override
     public DateTimeUnit minusYears( DateTimeUnit dateTimeUnit, int years )
     {
         DateTime dateTime = dateTimeUnit.toJodaDateTime( chronology );
-        return DateTimeUnit.fromJodaDateTime( dateTime.minusYears( years ) );
+        return DateTimeUnit.fromJodaDateTime( dateTime.minusYears( years ), dateTimeUnit.isIso8601() );
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java	2014-08-29 15:45:21 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/DateUnitPeriodTypeParser.java	2014-09-21 07:49:12 +0000
@@ -68,6 +68,12 @@
     @Override
     public DateInterval parse( String period )
     {
+        return parse( getCalendar(), period );
+    }
+
+    @Override
+    public DateInterval parse( Calendar calendar, String period )
+    {
         DateUnitType type = DateUnitType.find( period );
 
         if ( type == null )
@@ -97,15 +103,13 @@
             return null;
         }
 
-        Calendar calendar = getCalendar();
-
         if ( DateUnitType.DAILY.equals( type ) )
         {
             int year = Integer.parseInt( matcher.group( 1 ) );
             int month = Integer.parseInt( matcher.group( 2 ) );
             int day = Integer.parseInt( matcher.group( 3 ) );
 
-            DateTimeUnit dateTimeUnit = new DateTimeUnit( year, month, day );
+            DateTimeUnit dateTimeUnit = new DateTimeUnit( year, month, day, calendar.isIso8601() );
             dateTimeUnit.setDayOfWeek( calendar.weekday( dateTimeUnit ) );
 
             return new DateInterval( dateTimeUnit, dateTimeUnit );
@@ -120,7 +124,7 @@
                 return null;
             }
 
-            DateTimeUnit start = new DateTimeUnit( year, 1, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, 1, 1, calendar.isIso8601() );
             start = calendar.minusDays( start, calendar.weekday( start ) - 1 ); // rewind to start of week
 
             // since we rewind to start of week, we might end up in the previous years weeks, so we check and forward if needed
@@ -144,8 +148,8 @@
             int year = Integer.parseInt( matcher.group( 1 ) );
             int month = Integer.parseInt( matcher.group( 2 ) );
 
-            DateTimeUnit start = new DateTimeUnit( year, month, 1 );
-            DateTimeUnit end = new DateTimeUnit( year, month, calendar.daysInMonth( start.getYear(), start.getMonth() ) );
+            DateTimeUnit start = new DateTimeUnit( year, month, 1, calendar.isIso8601() );
+            DateTimeUnit end = new DateTimeUnit( year, month, calendar.daysInMonth( start.getYear(), start.getMonth() ), calendar.isIso8601() );
 
             start.setDayOfWeek( calendar.weekday( start ) );
             end.setDayOfWeek( calendar.weekday( end ) );
@@ -162,7 +166,7 @@
                 return null;
             }
 
-            DateTimeUnit start = new DateTimeUnit( year, (month * 2) - 1, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, (month * 2) - 1, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusMonths( end, 2 );
             end = calendar.minusDays( end, 1 );
@@ -183,7 +187,7 @@
                 return null;
             }
 
-            DateTimeUnit start = new DateTimeUnit( year, ((quarter - 1) * 3) + 1, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, ((quarter - 1) * 3) + 1, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusMonths( end, 3 );
             end = calendar.minusDays( end, 1 );
@@ -204,7 +208,7 @@
                 return null;
             }
 
-            DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 1 : 7, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 1 : 7, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusMonths( end, 6 );
             end = calendar.minusDays( end, 1 );
@@ -225,7 +229,7 @@
                 return null;
             }
 
-            DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 4 : 10, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, semester == 1 ? 4 : 10, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusMonths( end, 6 );
             end = calendar.minusDays( end, 1 );
@@ -239,9 +243,9 @@
         {
             int year = Integer.parseInt( matcher.group( 1 ) );
 
-            DateTimeUnit start = new DateTimeUnit( year, 1, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, 1, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( year, calendar.monthsInYear(),
-                calendar.daysInMonth( start.getYear(), calendar.monthsInYear() ) );
+                calendar.daysInMonth( start.getYear(), calendar.monthsInYear() ), calendar.isIso8601());
 
             start.setDayOfWeek( calendar.weekday( start ) );
             end.setDayOfWeek( calendar.weekday( end ) );
@@ -252,7 +256,7 @@
         {
             int year = Integer.parseInt( matcher.group( 1 ) );
 
-            DateTimeUnit start = new DateTimeUnit( year, 4, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, 4, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusYears( end, 1 );
             end = calendar.minusDays( end, 1 );
@@ -266,7 +270,7 @@
         {
             int year = Integer.parseInt( matcher.group( 1 ) );
 
-            DateTimeUnit start = new DateTimeUnit( year, 7, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, 7, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusYears( end, 1 );
             end = calendar.minusDays( end, 1 );
@@ -280,7 +284,7 @@
         {
             int year = Integer.parseInt( matcher.group( 1 ) );
 
-            DateTimeUnit start = new DateTimeUnit( year, 10, 1 );
+            DateTimeUnit start = new DateTimeUnit( year, 10, 1, calendar.isIso8601() );
             DateTimeUnit end = new DateTimeUnit( start );
             end = calendar.plusYears( end, 1 );
             end = calendar.minusDays( end, 1 );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java	2014-05-21 07:25:28 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/PeriodTypeParser.java	2014-09-21 07:49:12 +0000
@@ -34,4 +34,6 @@
 public interface PeriodTypeParser
 {
     public DateInterval parse( String period );
+
+    public DateInterval parse( Calendar calendar, String period );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java	2014-04-25 12:25:39 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/GregorianCalendar.java	2014-09-21 07:49:12 +0000
@@ -56,4 +56,10 @@
     {
         return "gregorian";
     }
+
+    @Override
+    public boolean isIso8601()
+    {
+        return true;
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java	2014-04-25 12:25:39 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/calendar/impl/Iso8601Calendar.java	2014-09-21 07:49:12 +0000
@@ -56,4 +56,10 @@
     {
         return "iso8601";
     }
+
+    @Override
+    public boolean isIso8601()
+    {
+        return true;
+    }
 }

=== modified file 'dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java'
--- dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java	2014-08-29 10:02:21 +0000
+++ dhis-2/dhis-api/src/test/java/org/hisp/dhis/calendar/DateTimeUnitPeriodTypeParserTest.java	2014-09-21 07:49:12 +0000
@@ -50,66 +50,66 @@
     public void testDateUnitFormatParser()
     {
         // daily
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 4 ), new DateTimeUnit( 2014, 2, 4 ) ), format.parse( "20140204" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 4, true ), new DateTimeUnit( 2014, 2, 4, true ) ), format.parse( "20140204" ) );
 
         // weekly
-        assertEquals( new DateInterval( new DateTimeUnit( 2013, 12, 30 ), new DateTimeUnit( 2014, 1, 5 ) ), format.parse( "2014W1" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 6 ), new DateTimeUnit( 2014, 1, 12 ) ), format.parse( "2014W2" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2013, 12, 30, true ), new DateTimeUnit( 2014, 1, 5, true ) ), format.parse( "2014W1" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 6, true ), new DateTimeUnit( 2014, 1, 12, true ) ), format.parse( "2014W2" ) );
 
         // monthly
         assertNull( format.parse( "2014W0" ) );
         assertNull( format.parse( "2014W53" ) );
         assertNotNull( format.parse( "2009W53" ) ); // 2009 has 53 weeks
         assertNull( format.parse( "2009W54" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 1 ), new DateTimeUnit( 2014, 2, 28 ) ), format.parse( "201402" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2014, 4, 30 ) ), format.parse( "201404" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1 ), new DateTimeUnit( 2014, 3, 31 ) ), format.parse( "2014-03" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1 ), new DateTimeUnit( 2014, 5, 31 ) ), format.parse( "2014-05" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 2, 1, true ), new DateTimeUnit( 2014, 2, 28, true ) ), format.parse( "201402" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2014, 4, 30, true ) ), format.parse( "201404" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1, true ), new DateTimeUnit( 2014, 3, 31, true ) ), format.parse( "2014-03" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1, true ), new DateTimeUnit( 2014, 5, 31, true ) ), format.parse( "2014-05" ) );
 
         // bi-monthly
         assertNull( format.parse( "201400B" ) );
         assertNull( format.parse( "201407B" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 2, 28 ) ), format.parse( "201401B" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1 ), new DateTimeUnit( 2014, 4, 30 ) ), format.parse( "201402B" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "201403B" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2014, 8, 31 ) ), format.parse( "201404B" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 9, 1 ), new DateTimeUnit( 2014, 10, 31 ) ), format.parse( "201405B" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 11, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "201406B" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 2, 28, true ) ), format.parse( "201401B" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 3, 1, true ), new DateTimeUnit( 2014, 4, 30, true ) ), format.parse( "201402B" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 5, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "201403B" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2014, 8, 31, true ) ), format.parse( "201404B" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 9, 1, true ), new DateTimeUnit( 2014, 10, 31, true ) ), format.parse( "201405B" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 11, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "201406B" ) );
 
         // quarter
         assertNull( format.parse( "2014Q0" ) );
         assertNull( format.parse( "2014Q5" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 3, 31 ) ), format.parse( "2014Q1" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "2014Q2" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2014, 9, 30 ) ), format.parse( "2014Q3" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "2014Q4" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 3, 31, true ) ), format.parse( "2014Q1" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "2014Q2" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2014, 9, 30, true ) ), format.parse( "2014Q3" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "2014Q4" ) );
 
         // six-monthly
         assertNull( format.parse( "2014S0" ) );
         assertNull( format.parse( "2014S3" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "2014S1" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "2014S2" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "2014S1" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "2014S2" ) );
 
         // six-monthly april
         assertNull( format.parse( "2014AprilS0" ) );
         assertNull( format.parse( "2014AprilS3" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2014, 9, 30 ) ), format.parse( "2014AprilS1" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1 ), new DateTimeUnit( 2015, 3, 31 ) ), format.parse( "2014AprilS2" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2014, 9, 30, true ) ), format.parse( "2014AprilS1" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1, true ), new DateTimeUnit( 2015, 3, 31, true ) ), format.parse( "2014AprilS2" ) );
 
         // yearly
-        assertEquals( new DateInterval( new DateTimeUnit( 2013, 1, 1 ), new DateTimeUnit( 2013, 12, 31 ) ), format.parse( "2013" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1 ), new DateTimeUnit( 2014, 12, 31 ) ), format.parse( "2014" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2013, 1, 1, true ), new DateTimeUnit( 2013, 12, 31, true ) ), format.parse( "2013" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 1, 1, true ), new DateTimeUnit( 2014, 12, 31, true ) ), format.parse( "2014" ) );
 
         // financial april
-        assertEquals( new DateInterval( new DateTimeUnit( 2013, 4, 1 ), new DateTimeUnit( 2014, 3, 31 ) ), format.parse( "2013April" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1 ), new DateTimeUnit( 2015, 3, 31 ) ), format.parse( "2014April" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2013, 4, 1, true ), new DateTimeUnit( 2014, 3, 31, true ) ), format.parse( "2013April" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 4, 1, true ), new DateTimeUnit( 2015, 3, 31, true ) ), format.parse( "2014April" ) );
 
         // financial july
-        assertEquals( new DateInterval( new DateTimeUnit( 2013, 7, 1 ), new DateTimeUnit( 2014, 6, 30 ) ), format.parse( "2013July" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1 ), new DateTimeUnit( 2015, 6, 30 ) ), format.parse( "2014July" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2013, 7, 1, true ), new DateTimeUnit( 2014, 6, 30, true ) ), format.parse( "2013July" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 7, 1, true ), new DateTimeUnit( 2015, 6, 30, true ) ), format.parse( "2014July" ) );
 
         // financial october
-        assertEquals( new DateInterval( new DateTimeUnit( 2013, 10, 1 ), new DateTimeUnit( 2014, 9, 30 ) ), format.parse( "2013Oct" ) );
-        assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1 ), new DateTimeUnit( 2015, 9, 30 ) ), format.parse( "2014Oct" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2013, 10, 1, true ), new DateTimeUnit( 2014, 9, 30, true ) ), format.parse( "2013Oct" ) );
+        assertEquals( new DateInterval( new DateTimeUnit( 2014, 10, 1, true ), new DateTimeUnit( 2015, 9, 30, true ) ), format.parse( "2014Oct" ) );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java	2014-09-14 19:39:53 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java	2014-09-21 07:49:12 +0000
@@ -86,6 +86,8 @@
 import org.hisp.dhis.analytics.DataQueryParams;
 import org.hisp.dhis.analytics.DimensionItem;
 import org.hisp.dhis.analytics.QueryPlanner;
+import org.hisp.dhis.calendar.Calendar;
+import org.hisp.dhis.calendar.DateTimeUnit;
 import org.hisp.dhis.common.AnalyticalObject;
 import org.hisp.dhis.common.BaseDimensionalObject;
 import org.hisp.dhis.common.CodeGenerator;
@@ -148,53 +150,53 @@
     implements AnalyticsService
 {
     private static final Log log = LogFactory.getLog( DefaultAnalyticsService.class );
-    
+
     private static final String VALUE_HEADER_NAME = "Value";
     private static final int PERCENT = 100;
     private static final int MAX_QUERIES = 8;
 
     //TODO make sure data x dims are successive
     //TODO completeness on time
-    
+
     @Autowired
     private AnalyticsManager analyticsManager;
-    
+
     @Autowired
     private AnalyticsSecurityManager securityManager;
-    
+
     @Autowired
     private QueryPlanner queryPlanner;
-    
+
     @Autowired
     private IndicatorService indicatorService;
-    
+
     @Autowired
     private DataElementService dataElementService;
-    
+
     @Autowired
     private DataElementCategoryService categoryService;
-    
+
     @Autowired
     private DataSetService dataSetService;
-    
+
     @Autowired
     private OrganisationUnitService organisationUnitService;
-    
+
     @Autowired
     private OrganisationUnitGroupService organisationUnitGroupService;
-    
+
     @Autowired
     private TrackedEntityAttributeService attributeService;
-    
+
     @Autowired
     private ExpressionService expressionService;
-    
+
     @Autowired
     private ConstantService constantService;
 
     @Autowired
     private DataElementOperandService operandService;
-    
+
     @Autowired
     private SystemSettingManager systemSettingManager;
 
@@ -212,19 +214,19 @@
 
     @Override
     public Grid getAggregatedDataValues( DataQueryParams params )
-    {   
+    {
         // ---------------------------------------------------------------------
         // Security and validation
         // ---------------------------------------------------------------------
 
         securityManager.decideAccess( params );
-        
+
         securityManager.applyDataApprovalConstraints( params );
-        
+
         securityManager.applyDimensionConstraints( params );
-        
+
         queryPlanner.validate( params );
-        
+
         params.conform();
 
         // ---------------------------------------------------------------------
@@ -232,7 +234,7 @@
         // ---------------------------------------------------------------------
 
         Grid grid = new ListGrid();
-        
+
         addHeaders( params, grid );
 
         // ---------------------------------------------------------------------
@@ -240,22 +242,22 @@
         // ---------------------------------------------------------------------
 
         addIndicatorValues( params, grid );
-        
+
         addDataElementValues( params, grid );
-        
+
         addDataSetValues( params, grid );
-        
+
         addDynamicDimensionValues( params, grid );
-        
+
         // ---------------------------------------------------------------------
         // Meta-data
         // ---------------------------------------------------------------------
 
         addMetaData( params, grid );
-        
+
         return grid;
     }
-    
+
     /**
      * Adds headers to the given grid based on the given data query parameters.
      */
@@ -265,24 +267,24 @@
         {
             grid.addHeader( new GridHeader( col.getDimension(), col.getDisplayName(), String.class.getName(), false, true ) );
         }
-        
+
         grid.addHeader( new GridHeader( DataQueryParams.VALUE_ID, VALUE_HEADER_NAME, Double.class.getName(), false, false ) );
     }
 
     /**
-     * Adds indicator values to the given grid based on the given data query 
+     * Adds indicator values to the given grid based on the given data query
      * parameters.
-     * 
+     *
      * @param params the data query parameters.
      * @param grid the grid.
      */
     private void addIndicatorValues( DataQueryParams params, Grid grid )
     {
         if ( params.getIndicators() != null )
-        {   
+        {
             int indicatorIndex = params.getIndicatorDimensionIndex();
             List<Indicator> indicators = asTypedList( params.getIndicators() );
-            
+
             expressionService.explodeExpressions( indicators );
 
             // -----------------------------------------------------------------
@@ -292,13 +294,13 @@
             DataQueryParams dataSourceParams = params.instance();
             dataSourceParams.removeDimension( DATAELEMENT_DIM_ID );
             dataSourceParams.removeDimension( DATASET_DIM_ID );
-            
+
             dataSourceParams = replaceIndicatorsWithDataElements( dataSourceParams, indicatorIndex );
 
             Map<String, Double> aggregatedDataMap = getAggregatedDataValueMap( dataSourceParams );
 
             Map<String, Map<DataElementOperand, Double>> permutationOperandValueMap = dataSourceParams.getPermutationOperandValueMap( aggregatedDataMap );
-            
+
             List<List<DimensionItem>> dimensionItemPermutations = dataSourceParams.getDimensionItemPermutations();
 
             Map<String, Double> constantMap = constantService.getConstantMap();
@@ -306,7 +308,7 @@
             Period filterPeriod = dataSourceParams.getFilterPeriod();
 
             Map<String, Map<String, Integer>> permutationOrgUnitTargetMap = getOrgUnitTargetMap( dataSourceParams, indicators );
-            
+
             for ( Indicator indicator : indicators )
             {
                 for ( List<DimensionItem> options : dimensionItemPermutations )
@@ -314,28 +316,28 @@
                     String permKey = DimensionItem.asItemKey( options );
 
                     Map<DataElementOperand, Double> valueMap = permutationOperandValueMap.get( permKey );
-                    
+
                     if ( valueMap == null )
                     {
                         continue;
                     }
-                    
+
                     Period period = filterPeriod != null ? filterPeriod : (Period) DimensionItem.getPeriodItem( options );
-                    
+
                     OrganisationUnit unit = (OrganisationUnit) DimensionItem.getOrganisationUnitItem( options );
-                    
+
                     String ou = unit != null ? unit.getUid() : null;
-                    
+
                     Map<String, Integer> orgUnitCountMap = permutationOrgUnitTargetMap != null ? permutationOrgUnitTargetMap.get( ou ) : null;
-                    
+
                     Double value = expressionService.getIndicatorValue( indicator, period, valueMap, constantMap, orgUnitCountMap, period.getDaysInPeriod() );
 
                     if ( value != null )
                     {
                         List<DimensionItem> row = new ArrayList<>( options );
-                        
+
                         row.add( indicatorIndex, new DimensionItem( INDICATOR_DIM_ID, indicator ) );
-                                                    
+
                         grid.addRow();
                         grid.addValues( DimensionItem.getItemIdentifiers( row ) );
                         grid.addValue( params.isSkipRounding() ? value : MathUtils.getRounded( value ) );
@@ -346,9 +348,9 @@
     }
 
     /**
-     * Adds data element values to the given grid based on the given data query 
+     * Adds data element values to the given grid based on the given data query
      * parameters.
-     * 
+     *
      * @param params the data query parameters.
      * @param grid the grid.
      */
@@ -359,9 +361,9 @@
             DataQueryParams dataSourceParams = params.instance();
             dataSourceParams.removeDimension( INDICATOR_DIM_ID );
             dataSourceParams.removeDimension( DATASET_DIM_ID );
-            
+
             Map<String, Double> aggregatedDataMap = getAggregatedDataValueMap( dataSourceParams );
-            
+
             for ( Map.Entry<String, Double> entry : aggregatedDataMap.entrySet() )
             {
                 grid.addRow();
@@ -372,9 +374,9 @@
     }
 
     /**
-     * Adds data set values to the given grid based on the given data query 
+     * Adds data set values to the given grid based on the given data query
      * parameters.
-     * 
+     *
      * @param params the data query parameters.
      * @param grid the grid.
      */
@@ -400,7 +402,7 @@
 
             List<Integer> completenessDimIndexes = dataSourceParams.getCompletenessDimensionIndexes();
             List<Integer> completenessFilterIndexes = dataSourceParams.getCompletenessFilterIndexes();
-            
+
             DataQueryParams targetParams = dataSourceParams.instance();
 
             targetParams.setDimensions( ListUtils.getAtIndexes( targetParams.getDimensions(), completenessDimIndexes ) );
@@ -415,7 +417,7 @@
             Map<String, PeriodType> dsPtMap = dataSourceParams.getDataSetPeriodTypeMap();
 
             PeriodType filterPeriodType = dataSourceParams.getFilterPeriodType();
-            
+
             // -----------------------------------------------------------------
             // Join data maps, calculate completeness and add to grid
             // -----------------------------------------------------------------
@@ -423,20 +425,20 @@
             for ( Map.Entry<String, Double> entry : aggregatedDataMap.entrySet() )
             {
                 List<String> dataRow = ListUtils.getList( entry.getKey().split( DIMENSION_SEP ) );
-                
+
                 List<String> targetRow = ListUtils.getAtIndexes( dataRow, completenessDimIndexes );
                 String targetKey = StringUtils.join( targetRow, DIMENSION_SEP );
                 Double target = targetMap.get( targetKey );
-                
+
                 if ( target != null && entry.getValue() != null )
                 {
                     PeriodType queryPt = filterPeriodType != null ? filterPeriodType : getPeriodTypeFromIsoString( dataRow.get( periodIndex ) );
                     PeriodType dataSetPt = dsPtMap.get( dataRow.get( dataSetIndex ) );
-                    
+
                     target = target * queryPt.getPeriodSpan( dataSetPt );
-                    
+
                     double value = entry.getValue() * PERCENT / target;
-                    
+
                     grid.addRow();
                     grid.addValues( dataRow.toArray() );
                     grid.addValue( params.isSkipRounding() ? value : MathUtils.getRounded( value ) );
@@ -446,9 +448,9 @@
     }
 
     /**
-     * Adds values to the given grid based on dynamic dimensions from the given 
+     * Adds values to the given grid based on dynamic dimensions from the given
      * data query parameters.
-     * 
+     *
      * @param params the data query parameters.
      * @param grid the grid.
      */
@@ -457,7 +459,7 @@
         if ( params.getIndicators() == null && params.getDataElements() == null && params.getDataSets() == null )
         {
             Map<String, Double> aggregatedDataMap = getAggregatedDataValueMap( params.instance() );
-            
+
             for ( Map.Entry<String, Double> entry : aggregatedDataMap.entrySet() )
             {
                 grid.addRow();
@@ -468,9 +470,9 @@
     }
 
     /**
-     * Adds meta data values to the given grid based on the given data query 
+     * Adds meta data values to the given grid based on the given data query
      * parameters.
-     * 
+     *
      * @param params the data query parameters.
      * @param grid the grid.
      */
@@ -479,32 +481,51 @@
         if ( !params.isSkipMeta() )
         {
             Integer cocIndex = params.getCocIndex();
-            
+
             Map<Object, Object> metaData = new HashMap<>();
-            
+
             Map<String, String> uidNameMap = getUidNameMap( params );
-            Map<String, String> cocNameMap = getCocNameMap( grid, cocIndex );            
+            Map<String, String> cocNameMap = getCocNameMap( grid, cocIndex );
             uidNameMap.putAll( cocNameMap );
-            
+
             metaData.put( NAMES_META_KEY, uidNameMap );
-            metaData.put( PERIOD_DIM_ID, getUids( params.getDimensionOrFilter( PERIOD_DIM_ID ) ) );
+
+            List<String> periodUids = new ArrayList<>();
+
+            Calendar calendar = PeriodType.getCalendar();
+
+            if ( calendar.isIso8601() )
+            {
+                periodUids = getUids( params.getDimensionOrFilter( PERIOD_DIM_ID ) );
+            }
+            else
+            {
+                for ( NameableObject nameableObject : params.getDimensionOrFilter( PERIOD_DIM_ID ) )
+                {
+                    Period period = (Period) nameableObject;
+                    DateTimeUnit dateTimeUnit = calendar.fromIso( DateTimeUnit.fromJdkDate( period.getStartDate() ) );
+                    periodUids.add( period.getPeriodType().getIsoDate( dateTimeUnit ) );
+                }
+            }
+
+            metaData.put( PERIOD_DIM_ID, periodUids );
             metaData.put( ORGUNIT_DIM_ID, getUids( params.getDimensionOrFilter( ORGUNIT_DIM_ID ) ) );
             metaData.put( CATEGORYOPTIONCOMBO_DIM_ID, cocNameMap.keySet() );
-            
+
             if ( params.isHierarchyMeta() )
             {
                 metaData.put( OU_HIERARCHY_KEY, getParentGraphMap( asTypedList( params.getDimensionOrFilter( ORGUNIT_DIM_ID ), OrganisationUnit.class ) ) );
             }
-            
+
             if ( params.isShowHierarchy() )
             {
                 metaData.put( OU_NAME_HIERARCHY_KEY, getParentNameGraphMap( asTypedList( params.getDimensionOrFilter( ORGUNIT_DIM_ID ), OrganisationUnit.class ), true ) );
             }
-            
+
             grid.setMetaData( metaData );
-        }        
+        }
     }
-    
+
     @Override
     public Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List<String> columns, List<String> rows )
     {
@@ -512,33 +533,33 @@
         {
             return getAggregatedDataValues( params );
         }
-        
+
         ListUtils.removeEmptys( columns );
         ListUtils.removeEmptys( rows );
-        
+
         queryPlanner.validateTableLayout( params, columns, rows );
-        
+
         ReportTable reportTable = new ReportTable();
-        
+
         List<NameableObject[]> tableColumns = new ArrayList<>();
         List<NameableObject[]> tableRows = new ArrayList<>();
 
         if ( columns != null )
-        {            
+        {
             for ( String dimension : columns )
             {
                 reportTable.getColumnDimensions().add( dimension );
-                
+
                 tableColumns.add( params.getDimensionArrayCollapseDxExplodeCoc( dimension ) );
             }
         }
-        
+
         if ( rows != null )
         {
             for ( String dimension : rows )
             {
                 reportTable.getRowDimensions().add( dimension );
-                
+
                 tableRows.add( params.getDimensionArrayCollapseDxExplodeCoc( dimension ) );
             }
         }
@@ -546,33 +567,33 @@
         reportTable.setGridColumns( new CombinationGenerator<>( tableColumns.toArray( IRT2D ) ).getCombinations() );
         reportTable.setGridRows( new CombinationGenerator<>( tableRows.toArray( IRT2D ) ).getCombinations() );
 
-        addIfEmpty( reportTable.getGridColumns() ); 
+        addIfEmpty( reportTable.getGridColumns() );
         addIfEmpty( reportTable.getGridRows() );
-        
+
         reportTable.setTitle( IdentifiableObjectUtils.join( params.getFilterItems() ) );
         reportTable.setHideEmptyRows( params.isHideEmptyRows() );
         reportTable.setShowHierarchy( params.isShowHierarchy() );
 
         Grid grid = getAggregatedDataValues( params );
-        
+
         Map<String, Double> valueMap = getAggregatedDataValueMapping( grid );
 
         return reportTable.getGrid( new ListGrid( grid.getMetaData() ), valueMap, false );
     }
-    
+
     @Override
     public Map<String, Double> getAggregatedDataValueMapping( DataQueryParams params )
     {
         Grid grid = getAggregatedDataValues( params );
-        
+
         return getAggregatedDataValueMapping( grid );
     }
-    
+
     @Override
     public Map<String, Double> getAggregatedDataValueMapping( AnalyticalObject object, I18nFormat format )
     {
         DataQueryParams params = getFromAnalyticalObject( object, format );
-        
+
         return getAggregatedDataValueMapping( params );
     }
 
@@ -581,71 +602,71 @@
     // -------------------------------------------------------------------------
 
     /**
-     * Generates a mapping of permutations keys (organisation unit id or null) 
+     * Generates a mapping of permutations keys (organisation unit id or null)
      * and mappings of organisation unit group and counts.
-     * 
+     *
      * @param params the data query parameters.
-     * @param indicators the indicators for which formulas to scan for organisation 
+     * @param indicators the indicators for which formulas to scan for organisation
      *        unit groups.
      * @return a map of maps.
      */
     private Map<String, Map<String, Integer>> getOrgUnitTargetMap( DataQueryParams params, Collection<Indicator> indicators )
     {
         Set<OrganisationUnitGroup> orgUnitGroups = expressionService.getOrganisationUnitGroupsInIndicators( indicators );
-        
+
         if ( orgUnitGroups == null || orgUnitGroups.isEmpty() )
         {
             return null;
         }
-        
+
         DataQueryParams orgUnitTargetParams = params.instance().pruneToDimensionType( DimensionType.ORGANISATIONUNIT );
         orgUnitTargetParams.getDimensions().add( new BaseDimensionalObject( DimensionalObject.ORGUNIT_GROUP_DIM_ID, null, new ArrayList<NameableObject>( orgUnitGroups ) ) );
         orgUnitTargetParams.setSkipPartitioning( true );
-        
+
         Map<String, Double> orgUnitCountMap = getAggregatedOrganisationUnitTargetMap( orgUnitTargetParams );
-        
+
         return orgUnitTargetParams.getPermutationOrgUnitGroupCountMap( orgUnitCountMap );
     }
-    
+
     /**
      * Generates a mapping where the key represents the dimensional item identifiers
      * concatenated by "-" and the value is the corresponding aggregated data value
      * based on the given grid.
-     * 
+     *
      * @param grid the grid.
      * @return a mapping between item identifiers and aggregated values.
      */
     private Map<String, Double> getAggregatedDataValueMapping( Grid grid )
     {
         Map<String, Double> map = new HashMap<>();
-        
+
         int metaCols = grid.getWidth() - 1;
         int valueIndex = grid.getWidth() - 1;
-        
+
         for ( List<Object> row : grid.getRows() )
         {
             StringBuilder key = new StringBuilder();
-            
+
             for ( int index = 0; index < metaCols; index++ )
             {
                 key.append( row.get( index ) ).append( DIMENSION_SEP );
             }
 
             key.deleteCharAt( key.length() - 1 );
-            
+
             Double value = (Double) row.get( valueIndex );
-            
+
             map.put( key.toString(), value );
         }
-        
+
         return map;
     }
 
     /**
-     * Generates aggregated values for the given query. Creates a mapping between 
-     * a dimension key and the aggregated value. The dimension key is a 
+     * Generates aggregated values for the given query. Creates a mapping between
+     * a dimension key and the aggregated value. The dimension key is a
      * concatenation of the identifiers of the dimension items separated by "-".
-     * 
+     *
      * @param params the data query parameters.
      * @return a mapping between a dimension key and the aggregated value.
      */
@@ -655,10 +676,10 @@
     }
 
     /**
-     * Generates aggregated values for the given query. Creates a mapping between 
-     * a dimension key and the aggregated value. The dimension key is a 
+     * Generates aggregated values for the given query. Creates a mapping between
+     * a dimension key and the aggregated value. The dimension key is a
      * concatenation of the identifiers of the dimension items separated by "-".
-     * 
+     *
      * @param params the data query parameters.
      * @return a mapping between a dimension key and the aggregated value.
      */
@@ -670,7 +691,7 @@
     /**
      * Generates a mapping between the the data set dimension key and the count
      * of expected data sets to report.
-     * 
+     *
      * @param params the data query parameters.
      * @return a mapping between the the data set dimension key and the count of
      *         expected data sets to report.
@@ -684,7 +705,7 @@
      * Generates a mapping between the the org unit dimension key and the count
      * of org units inside the subtree of the given organisation units and
      * members of the given organisation unit groups.
-     * 
+     *
      * @param params the data query parameters.
      * @return a mapping between the the data set dimension key and the count of
      *         expected data sets to report.
@@ -693,43 +714,43 @@
     {
         return getAggregatedValueMap( params, ORGUNIT_TARGET_TABLE_NAME );
     }
-    
+
     /**
      * Generates a mapping between a dimension key and the aggregated value. The
      * dimension key is a concatenation of the identifiers of the dimension items
      * separated by "-".
-     * 
+     *
      * @param params the data query parameters.
      */
-    private Map<String, Double> getAggregatedValueMap( DataQueryParams params, String tableName )        
+    private Map<String, Double> getAggregatedValueMap( DataQueryParams params, String tableName )
     {
         queryPlanner.validateMaintenanceMode();
-        
+
         int optimalQueries = MathUtils.getWithin( getProcessNo(), 1, MAX_QUERIES );
-        
+
         Timer t = new Timer().start();
-        
+
         DataQueryGroups queryGroups = queryPlanner.planQuery( params, optimalQueries, tableName );
-        
+
         t.getSplitTime( "Planned query, got: " + queryGroups.getLargestGroupSize() + " for optimal: " + optimalQueries );
 
         Map<String, Double> map = new HashMap<>();
-        
+
         for ( List<DataQueryParams> queries : queryGroups.getSequentialQueries() )
         {
             List<Future<Map<String, Double>>> futures = new ArrayList<>();
-            
+
             for ( DataQueryParams query : queries )
             {
                 futures.add( analyticsManager.getAggregatedDataValues( query ) );
             }
-    
+
             for ( Future<Map<String, Double>> future : futures )
             {
                 try
                 {
                     Map<String, Double> taskValues = future.get();
-                    
+
                     if ( taskValues != null )
                     {
                         map.putAll( taskValues );
@@ -739,16 +760,16 @@
                 {
                     log.error( DebugUtils.getStackTrace( ex ) );
                     log.error( DebugUtils.getStackTrace( ex.getCause() ) );
-                    
+
                     throw new RuntimeException( "Error during execution of aggregation query task", ex );
                 }
             }
-            
+
             t.getSplitTime( "Got aggregated values for query group" );
         }
-        
+
         t.getTime( "Got aggregated values" );
-        
+
         return map;
     }
 
@@ -757,21 +778,21 @@
     // -------------------------------------------------------------------------
 
     @Override
-    public DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType, 
+    public DataQueryParams getFromUrl( Set<String> dimensionParams, Set<String> filterParams, AggregationType aggregationType,
         String measureCriteria, boolean skipMeta, boolean skipRounding, boolean hierarchyMeta, boolean ignoreLimit, boolean hideEmptyRows, boolean showHierarchy, I18nFormat format )
     {
         DataQueryParams params = new DataQueryParams();
 
         params.setAggregationType( aggregationType );
         params.setIgnoreLimit( ignoreLimit );
-        
+
         if ( dimensionParams != null && !dimensionParams.isEmpty() )
         {
             for ( String param : dimensionParams )
             {
                 String dimension = DimensionalObjectUtils.getDimensionFromParam( param );
                 List<String> options = DimensionalObjectUtils.getDimensionItemsFromParam( param );
-                
+
                 if ( dimension != null && options != null )
                 {
                     params.getDimensions().addAll( getDimension( dimension, options, null, format, false ) );
@@ -785,19 +806,19 @@
             {
                 String dimension = DimensionalObjectUtils.getDimensionFromParam( param );
                 List<String> options = DimensionalObjectUtils.getDimensionItemsFromParam( param );
-                
+
                 if ( dimension != null && options != null )
                 {
                     params.getFilters().addAll( getDimension( dimension, options, null, format, false ) );
                 }
             }
         }
-        
+
         if ( measureCriteria != null && !measureCriteria.isEmpty() )
         {
             params.setMeasureCriteria( DataQueryParams.getMeasureCriteriaFromParam( measureCriteria ) );
         }
-        
+
         params.setSkipMeta( skipMeta );
         params.setSkipRounding( skipRounding );
         params.setHierarchyMeta( hierarchyMeta );
@@ -811,123 +832,123 @@
     public DataQueryParams getFromAnalyticalObject( AnalyticalObject object, I18nFormat format )
     {
         DataQueryParams params = new DataQueryParams();
-        
+
         if ( object != null )
         {
             Date date = object.getRelativePeriodDate();
-            
+
             object.populateAnalyticalProperties();
-            
+
             for ( DimensionalObject column : object.getColumns() )
             {
                 params.getDimensions().addAll( getDimension( toDimension( column.getDimension() ), getUids( column.getItems() ), date, format, false ) );
             }
-            
+
             for ( DimensionalObject row : object.getRows() )
             {
                 params.getDimensions().addAll( getDimension( toDimension( row.getDimension() ), getUids( row.getItems() ), date, format, false ) );
             }
-            
+
             for ( DimensionalObject filter : object.getFilters() )
             {
                 params.getFilters().addAll( getDimension( toDimension( filter.getDimension() ), getUids( filter.getItems() ), date, format, false ) );
             }
         }
-        
+
         return params;
     }
-    
+
     // TODO verify that current user can read each dimension and dimension item
     // TODO optimize so that org unit levels + boundary are used in query instead of fetching all org units one by one
-    
+
     public List<DimensionalObject> getDimension( String dimension, List<String> items, Date relativePeriodDate, I18nFormat format, boolean allowNull )
-    {        
+    {
         if ( DATA_X_DIM_ID.equals( dimension ) )
         {
             List<DimensionalObject> dataDimensions = new ArrayList<>();
-            
+
             List<NameableObject> indicators = new ArrayList<>();
             List<NameableObject> dataElements = new ArrayList<>();
             List<NameableObject> dataSets = new ArrayList<>();
             List<NameableObject> operandDataElements = new ArrayList<>();
-            
+
             options : for ( String uid : items )
             {
                 Indicator in = indicatorService.getIndicator( uid );
-                
+
                 if ( in != null )
                 {
                     indicators.add( in );
                     continue options;
                 }
-                
+
                 DataElement de = dataElementService.getDataElement( uid );
-                
+
                 if ( de != null )
-                {       
+                {
                     dataElements.add( de );
                     continue options;
                 }
-                
+
                 DataSet ds = dataSetService.getDataSet( uid );
-                
+
                 if ( ds != null )
                 {
                     dataSets.add( ds );
                     continue options;
                 }
-                
+
                 DataElementOperand dc = operandService.getDataElementOperandByUid( uid );
-                
+
                 if ( dc != null )
                 {
                     operandDataElements.add( dc.getDataElement() );
                     continue options;
                 }
-                
-                throw new IllegalQueryException( "Data dimension option identifier does not reference any option: " + uid );                
+
+                throw new IllegalQueryException( "Data dimension option identifier does not reference any option: " + uid );
             }
-            
+
             if ( !indicators.isEmpty() )
             {
                 dataDimensions.add( new BaseDimensionalObject( INDICATOR_DIM_ID, DimensionType.INDICATOR, indicators ) );
             }
-            
+
             if ( !dataElements.isEmpty() )
             {
                 dataDimensions.add( new BaseDimensionalObject( DATAELEMENT_DIM_ID, DimensionType.DATAELEMENT, dataElements ) );
             }
-            
+
             if ( !dataSets.isEmpty() )
             {
                 dataDimensions.add( new BaseDimensionalObject( DATASET_DIM_ID, DimensionType.DATASET, dataSets ) );
             }
-            
+
             if ( !operandDataElements.isEmpty() )
             {
                 dataDimensions.add( new BaseDimensionalObject( DATAELEMENT_DIM_ID, DimensionType.DATAELEMENT, operandDataElements ) );
                 dataDimensions.add( new BaseDimensionalObject( CATEGORYOPTIONCOMBO_DIM_ID, DimensionType.CATEGORY_OPTION_COMBO, new ArrayList<NameableObject>() ) );
             }
-            
+
             if ( indicators.isEmpty() && dataElements.isEmpty() && dataSets.isEmpty() && operandDataElements.isEmpty() )
             {
                 throw new IllegalQueryException( "Dimension dx is present in query without any valid dimension options" );
             }
-            
+
             return dataDimensions;
         }
-        
+
         if ( CATEGORYOPTIONCOMBO_DIM_ID.equals( dimension ) )
         {
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORY_OPTION_COMBO, null, DISPLAY_NAME_CATEGORYOPTIONCOMBO, new ArrayList<NameableObject>() );
-            
+
             return ListUtils.getList( object );
         }
 
         if ( PERIOD_DIM_ID.equals( dimension ) )
         {
             Set<Period> periods = new HashSet<>();
-            
+
             for ( String isoPeriod : items )
             {
                 if ( RelativePeriodEnum.contains( isoPeriod ) )
@@ -938,19 +959,19 @@
                 else
                 {
                     Period period = PeriodType.getPeriodFromIsoString( isoPeriod );
-                
+
                     if ( period != null )
                     {
                         periods.add( period );
                     }
                 }
             }
-            
+
             if ( periods.isEmpty() )
             {
                 throw new IllegalQueryException( "Dimension pe is present in query without any valid dimension options" );
             }
-            
+
             for ( Period period : periods )
             {
                 period.setName( format != null ? format.formatPeriod( period ) : null );
@@ -958,20 +979,20 @@
 
             List<Period> periodList = new ArrayList<>( periods );
             Collections.sort( periodList, AscendingPeriodEndDateComparator.INSTANCE );
-            
+
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.PERIOD, null, DISPLAY_NAME_PERIOD, asList( periodList ) );
-            
+
             return ListUtils.getList( object );
         }
-        
+
         if ( ORGUNIT_DIM_ID.equals( dimension ) )
         {
             User user = currentUserService.getCurrentUser();
-            
+
             List<NameableObject> ous = new UniqueArrayList<>();
             List<Integer> levels = new UniqueArrayList<>();
             List<OrganisationUnitGroup> groups = new UniqueArrayList<>();
-            
+
             for ( String ou : items )
             {
                 if ( KEY_USER_ORGUNIT.equals( ou ) && user != null && user.hasDataViewOrganisationUnitWithFallback() )
@@ -989,7 +1010,7 @@
                 else if ( ou != null && ou.startsWith( KEY_LEVEL ) )
                 {
                     int level = DimensionalObjectUtils.getLevelFromLevelParam( ou );
-                    
+
                     if ( level > 0 )
                     {
                         levels.add( level );
@@ -998,9 +1019,9 @@
                 else if ( ou != null && ou.startsWith( KEY_ORGUNIT_GROUP ) )
                 {
                     String uid = DimensionalObjectUtils.getUidFromOrgUnitGroupParam( ou );
-                    
+
                     OrganisationUnitGroup group = organisationUnitGroupService.getOrganisationUnitGroup( uid );
-                    
+
                     if ( uid != null )
                     {
                         groups.add( group );
@@ -1009,134 +1030,134 @@
                 else if ( CodeGenerator.isValidCode( ou ) )
                 {
                     OrganisationUnit unit = organisationUnitService.getOrganisationUnit( ou );
-                    
+
                     if ( unit != null )
                     {
                         ous.add( unit );
                     }
                 }
             }
-            
+
             List<NameableObject> orgUnits = new UniqueArrayList<>();
             List<OrganisationUnit> ousList = NameableObjectUtils.asTypedList( ous );
-            
+
             if ( !levels.isEmpty() )
             {
                 orgUnits.addAll( organisationUnitService.getOrganisationUnitsAtLevels( levels, ousList ) );
             }
-            
+
             if ( !groups.isEmpty() )
             {
                 orgUnits.addAll( organisationUnitService.getOrganisationUnits( groups, ousList ) );
             }
-            
+
             if ( levels.isEmpty() && groups.isEmpty() )
             {
                 orgUnits.addAll( ous );
-            }            
-            
+            }
+
             if ( orgUnits.isEmpty() )
             {
                 throw new IllegalQueryException( "Dimension ou is present in query without any valid dimension options" );
             }
-            
+
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ORGANISATIONUNIT, null, DISPLAY_NAME_ORGUNIT, orgUnits );
-            
+
             return ListUtils.getList( object );
         }
-        
+
         if ( LONGITUDE_DIM_ID.contains( dimension ) )
         {
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LONGITUDE, new ArrayList<NameableObject>() );
-            
+
             return ListUtils.getList( object );
         }
 
         if ( LATITUDE_DIM_ID.contains( dimension ) )
         {
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.STATIC, null, DISPLAY_NAME_LATITUDE, new ArrayList<NameableObject>() );
-            
+
             return ListUtils.getList( object );
         }
-        
+
         OrganisationUnitGroupSet ougs = organisationUnitGroupService.getOrganisationUnitGroupSet( dimension );
-            
+
         if ( ougs != null )
         {
             List<NameableObject> ous = asList( organisationUnitGroupService.getOrganisationUnitGroupsByUid( items ) );
-            
+
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.ORGANISATIONUNIT_GROUPSET, null, ougs.getDisplayName(), ous );
-            
+
             return ListUtils.getList( object );
         }
-        
+
         DataElementGroupSet degs = dataElementService.getDataElementGroupSet( dimension );
-        
+
         if ( degs != null )
         {
             List<NameableObject> des = asList( dataElementService.getDataElementGroupsByUid( items ) );
-            
+
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.DATAELEMENT_GROUPSET, null, degs.getDisplayName(), des );
-            
+
             return ListUtils.getList( object );
         }
-        
+
         CategoryOptionGroupSet cogs = categoryService.getCategoryOptionGroupSet( dimension );
-        
+
         if ( cogs != null )
         {
             List<NameableObject> cogz = asList( categoryService.getCategoryOptionGroupsByUid( items ) );
-            
+
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORYOPTION_GROUPSET, null, cogs.getDisplayName(), cogz );
-            
+
             return ListUtils.getList( object );
         }
-        
+
         DataElementCategory dec = categoryService.getDataElementCategory( dimension );
-        
+
         if ( dec != null && dec.isDataDimension() )
         {
             List<NameableObject> decos = asList( categoryService.getDataElementCategoryOptionsByUid( items ) );
-            
+
             DimensionalObject object = new BaseDimensionalObject( dimension, DimensionType.CATEGORY, null, dec.getDisplayName(), decos );
-            
+
             return ListUtils.getList( object );
         }
-                
+
         if ( allowNull )
         {
             return null;
         }
-        
+
         throw new IllegalQueryException( "Dimension identifier does not reference any dimension: " + dimension );
     }
 
     // -------------------------------------------------------------------------
     // Supportive methods
     // -------------------------------------------------------------------------
-    
+
     /**
      * Replaces the indicator dimension including items with the data elements
      * part of the indicator expressions.
-     * 
+     *
      * @param params the data query parameters.
      * @param indicatorIndex the index of the indicator dimension in the given query.
      */
     private DataQueryParams replaceIndicatorsWithDataElements( DataQueryParams params, int indicatorIndex )
     {
-        List<Indicator> indicators = asTypedList( params.getIndicators() );        
+        List<Indicator> indicators = asTypedList( params.getIndicators() );
         List<NameableObject> dataElements = asList( expressionService.getDataElementsInIndicators( indicators ) );
-        
+
         params.getDimensions().set( indicatorIndex, new BaseDimensionalObject( DATAELEMENT_DIM_ID, DimensionType.DATAELEMENT, dataElements ) );
         params.enableCategoryOptionCombos();
-        
+
         return params;
     }
-    
+
     /**
-     * Returns a mapping between the identifier and the name of all dimension and 
+     * Returns a mapping between the identifier and the name of all dimension and
      * filter items for the given parameters.
-     * 
+     *
      * @param params the data query.
      */
     private Map<String, String> getUidNameMap( DataQueryParams params )
@@ -1145,32 +1166,32 @@
         map.putAll( getUidNameMap( params.getDimensions(), params.isHierarchyMeta() ) );
         map.putAll( getUidNameMap( params.getFilters(), params.isHierarchyMeta() ) );
         map.put( DATA_X_DIM_ID, DISPLAY_NAME_DATA_X );
-        
+
         return map;
     }
 
     /**
      * Returns a mapping between identifiers and names for the given dimensional
      * objects.
-     * 
+     *
      * @param dimensions the dimensional objects.
-     * @param hierarchyMeta indicates whether to include meta data of the 
+     * @param hierarchyMeta indicates whether to include meta data of the
      *        organisation unit hierarchy.
      */
     private Map<String, String> getUidNameMap( List<DimensionalObject> dimensions, boolean hierarchyMeta )
     {
         Map<String, String> map = new HashMap<>();
-        
+
         for ( DimensionalObject dimension : dimensions )
         {
             List<NameableObject> items = new ArrayList<>( dimension.getItems() );
 
             boolean hierarchy = hierarchyMeta && DimensionType.ORGANISATIONUNIT.equals( dimension.getDimensionType() );
-            
+
             // -----------------------------------------------------------------
             // If dimension is not fixed and has no options, insert all options
             // -----------------------------------------------------------------
-            
+
             if ( !FIXED_DIMS.contains( dimension.getDimension() ) && items.isEmpty() )
             {
                 if ( DimensionType.ORGANISATIONUNIT_GROUPSET.equals( dimension.getDimensionType() ) )
@@ -1194,52 +1215,63 @@
             // -----------------------------------------------------------------
             // Insert UID and name into map
             // -----------------------------------------------------------------
-            
+
+            Calendar calendar = PeriodType.getCalendar();
+
             for ( IdentifiableObject idObject : items )
             {
-                map.put( idObject.getUid(), idObject.getDisplayName() );
-                
+                if ( !calendar.isIso8601() && Period.class.isInstance( idObject ) )
+                {
+                    Period period = (Period) idObject;
+                    DateTimeUnit dateTimeUnit = calendar.fromIso( DateTimeUnit.fromJdkDate( period.getStartDate() ) );
+                    map.put( period.getPeriodType().getIsoDate( dateTimeUnit ), idObject.getDisplayName() );
+                }
+                else
+                {
+                    map.put( idObject.getUid(), idObject.getDisplayName() );
+                }
+
                 if ( hierarchy )
                 {
                     OrganisationUnit unit = (OrganisationUnit) idObject;
-                    
+
                     map.putAll( IdentifiableObjectUtils.getUidNameMap( unit.getAncestors() ) );
                 }
             }
-            
+
             if ( dimension.getDisplayName() != null )
             {
                 map.put( dimension.getDimension(), dimension.getDisplayName() );
             }
         }
-        
+
         return map;
     }
-    
+
     /**
      * Returns a mapping between the category option combo identifiers and names
      * in the given grid. Returns an empty map if the grid or cocIndex parameters
      * are null.
-     * 
+     *
      * @param grid the grid.
      * @param cocIndex the category option combo index in the grid.
      */
     private Map<String, String> getCocNameMap( Grid grid, Integer cocIndex )
     {
         Map<String, String> metaData = new HashMap<>();
-        
+
         if ( grid != null && cocIndex != null )
         {
             Set<String> uids = new HashSet<>( ConversionUtils.<String>cast( grid.getColumn( cocIndex ) ) );
-            
+
             Collection<DataElementCategoryOptionCombo> cocs = categoryService.getDataElementCategoryOptionCombosByUid( uids );
-            
+
             for ( DataElementCategoryOptionCombo coc : cocs )
             {
                 metaData.put( coc.getUid(), coc.getName() );
             }
         }
-        
+
         return metaData;
     }
 
@@ -1251,7 +1283,7 @@
     private int getProcessNo()
     {
         Integer cores = (Integer) systemSettingManager.getSystemSetting( SystemSettingManager.KEY_DATABASE_SERVER_CPUS );
-        
+
         return ( cores == null || cores == 0 ) ? SystemUtils.getCpuCores() : cores;
     }
 }