CodeSVby CA Technologies

Magic Dates

< Back

Prerequisites

CodeSV supports generation of magic dates. There are two possible magic dates, the first one is based on the current date that is computed when the response is created and the second one is based on information from the request.

The functionality of magic dates is by default turned ON but it is possible to disable it with the API:

@Test
public void disableMagicStrings() throws Exception {
    forGet(URL)
        .doReturn(
            okMessage()
                // Reference a date/time from arguments of the request (query) and format it to default format (yyyy-MM-dd'T'HH:mm:ss.sssX)
                .withHeader("requestTime", "${argument.requestTime:ISO_LOCAL_TIME}")
                // Reference a date/time from attributes of the request (URL parameters), apply offset minut 2 weeks and format it to default format (yyyy-MM-dd'T'HH:mm:ss.sssX)
                .withHeader("lastModification", "${attribute.date:\"yyyyMMdd\":-2w}")
                // Reference a date/time from metadata of the request (headers) and format it to ISO_OFFSET_DATE_TIME format (yyyy-MM-dd'T'HH:mm:ssXXX)
                .withHeader("dateOfCreation",
                    "${metadata.currentDate:\"yyyy-MM-dd'T'HH:mm:ss\":ISO_OFFSET_DATE_TIME}")
                .withJsonBody(JSON_EXAMPLES_PORTFOLIO_SOURCE_DATE)
                .disableMagicDates()
        );
}

Magic Dates Based on Current Date

This type of magic date has the following pattern:

${currentDate:<offset>:<format>}

Where currentDate specifies that the service should generate a magic date based on the current date/time of response. offset and format are optional parameters.

The offset syntax is “+” or “-“ followed by a time specification that will be applied to generated date. The time specification supports these parameters:

  • seconds (s)
  • minutes (m)
  • hours (h)
  • days (d)
  • week (w)

The format represents the date format that will be returned. It is possible to specify a custom format, for example; "yyyyMMdd" that should follow the syntax from java7 or use predefined pattern names e.g. ISO_DATE.

Example of Using Magic Dates

private static final String URL = "http://www.ca.com/portfolio/";

  private static final String JSON_EXAMPLES_PORTFOLIO_CURRENT_DATE = "{"
      + "\"portfolio\": {\n"
      + "   \"id\": \"1\",\n"
      + "   \"dateOfRequest\": \"${currentDate:+7d:\"yyyy-MM-dd\"}\",\n"
      + "   \"productNamesList\": [\n"
      + "    \"CA Server Automation\",\n"
      + "    \"CA Service Catalog\",\n"
      + "    \"CA Service Desk Manager\",\n"
      + "    \"CA Service Management\",\n"
      + "    \"CA Service Operations Insight\",\n"
      + "    \"CA Service Virtualization\"\n"
      + "  ]\n"
      + "}}";

  @Rule
  public VirtualServerRule vs = new VirtualServerRule();

  @Test
  public void testCurrentDateMagicDate() throws Exception {
    forGet(URL)
        .doReturn(
            okMessage()
                // Format current date to ISO_LOCAL_DATE_TIME format (yyyy-MM-dd)
                .withHeader("lastRequest", "${currentDate:ISO_LOCAL_DATE_TIME}")
                // Create current date with offset minus 1 week and format it to default format (yyyy-MM-dd'T'HH:mm:ss.sssX)
                .withHeader("lastModification", "${currentDate:-1w}")
                // Create current date with offset minus 1 hour and format it to ISO_OFFSET_DATE_TIME format (yyyy-MM-dd'T'HH:mm:ssXXX)
                .withHeader("dateOfCreation", "${currentDate:-1h:ISO_OFFSET_DATE_TIME}")
                .withJsonBody(JSON_EXAMPLES_PORTFOLIO_CURRENT_DATE)
        );

    HttpClient client = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet(URL);
    request.addHeader("Language", "en_us");

    HttpResponse response = client.execute(request);

    BufferedReader reader = new BufferedReader(
        new InputStreamReader(response.getEntity().getContent()));
    StringBuffer result = new StringBuffer();
    String line;
    while ((line = reader.readLine()) != null) {
      result.append(line);
    }

    String body = result.toString().replaceAll("\\s+", "");

    assertEquals(200, response.getStatusLine().getStatusCode());
    assertNotNull(body);

    LocalDateTime nextWeek = LocalDateTime.now().plusDays(7);
    assertTrue(body.contains(nextWeek.format(DateTimeFormatter.ISO_DATE)));

    // Asserting time of the creation of the response is impossible, just check different formats and offsets
    System.out.println(
        "${currentDate:ISO_LOCAL_DATE_TIME} generated " + response.getFirstHeader("lastRequest")
            .getValue());
    System.out
        .println("${currentDate:-1w} generated " + response.getFirstHeader("lastModification")
            .getValue());
    System.out.println("${currentDate:-1h:ISO_OFFSET_DATE_TIME} generated " + response
        .getFirstHeader("dateOfCreation").getValue());
  }
}

For a complete example see: CurrentMagicDateExample

Magic Dates From a Source

This type of magic date is using the pattern:

${source:sourceFormat:<offset>:<format>}

 

Where source can be any magic string reference, sourceFormat is a format in which source should be interpreted. The sourceFormat has the same specification as format in previous types of magic date. offset and format are optional and they have exactly the same meaning and possibilities as in current date magic date.

Example of Using Magic Dates

private static final String JSON_EXAMPLES_PORTFOLIO_SOURCE_DATE = "{"
     + "\"portfolio\": {\n"
     + "   \"id\": \"1\",\n"
     + "   \"dateOfRequest\": \"${metadata.time:\"HH:mm:ss\":+4h:ISO_LOCAL_TIME}\",\n"
     + "   \"productNamesList\": [\n"
     + "    \"CA Server Automation\",\n"
     + "    \"CA Service Catalog\",\n"
     + "    \"CA Service Desk Manager\",\n"
     + "    \"CA Service Management\",\n"
     + "    \"CA Service Operations Insight\",\n"
     + "    \"CA Service Virtualization\"\n"
     + "  ]\n"
     + "}}";

 private static final String URL = "http://www.ca.com/portfolio/{date}?requestTime=16%3A00%3A01";

 @Test
   public void testSourceMagicDate() throws Exception {
     forGet(URL)
         .doReturn(
             okMessage()
                 // Reference a date/time from arguments of the request (query) and format it to default format (yyyy-MM-dd'T'HH:mm:ss.sssX)
                 .withHeader("requestTime", "${argument.requestTime:ISO_LOCAL_TIME}")
                 // Reference a date/time from attributes of the request (URL parameters), apply offset minut 2 weeks and format it to default format (yyyy-MM-dd'T'HH:mm:ss.sssX)
                 .withHeader("lastModification", "${attribute.date:\"yyyyMMdd\":-2w}")
                 // Reference a date/time from metadata of the request (headers) and format it to ISO_OFFSET_DATE_TIME format (yyyy-MM-dd'T'HH:mm:ssXXX)
                 .withHeader("dateOfCreation",
                     "${metadata.currentDate:\"yyyy-MM-dd'T'HH:mm:ss\":ISO_OFFSET_DATE_TIME}")
                 .withJsonBody(JSON_EXAMPLES_PORTFOLIO_SOURCE_DATE)
         );
 
     HttpClient client = HttpClientBuilder.create().build();
     HttpGet request = new HttpGet("http://www.ca.com/portfolio/20170814?requestTime=16%3A00%3A01");
     request.addHeader("time", "15:30:49");
     request.addHeader("currentDate", "2017-08-14T14:50:10");
     HttpResponse response;
 
     response = client.execute(request);
     BufferedReader reader = new BufferedReader(
         new InputStreamReader(response.getEntity().getContent()));
     StringBuffer result = new StringBuffer();
     String line;
     while ((line = reader.readLine()) != null) {
       result.append(line);
     }
 
     String body = result.toString().replaceAll("\\s+", "");
 
     assertEquals(200, response.getStatusLine().getStatusCode());
     assertNotNull(body);
     assertTrue(body.contains("19:30:49"));
 
     System.out.println(
         "${argument.requestTime:ISO_LOCAL_TIME} generated " + response.getFirstHeader("requestTime")
             .getValue());
     System.out.println("${attribute.date:\"yyyyMMdd\":-2w} generated " + response
         .getFirstHeader("lastModification").getValue());
     System.out.println(
         "${metadata.currentDate:\"yyyy-MM-dd'T'HH:mm:ss\":ISO_OFFSET_DATE_TIME} generated "
             + response.getFirstHeader("dateOfCreation").getValue());
 
     // Created strings can have different timezone offsets depending on timezone of your machine
     assertEquals("1970-01-01T16:00:01.001+01", response.getFirstHeader("requestTime").getValue());
     assertEquals("2017-07-31T00:00:00.000+02",
         response.getFirstHeader("lastModification").getValue());
     assertEquals("2017-08-14T14:50:10+02:00", response.getFirstHeader("dateOfCreation").getValue());
   }

For a complete example see: SourceMagicDateExample

Supported Patterns Names

/**
   * The ISO date format that formats or parses a ISO-8601 date format, such as
   * '2011-12-03T10:15:30+01:00'. This is default format used by magic dates if format is not
   * provided.
   */
  ISO_DEFAULT = "yyyy-MM-dd'T'HH:mm:ss.sssX"

  /**
   * The ISO date format that formats or parses a ISO-8601 extended local date without an offset,
   * such as '2011-12-03'.
   */
  ISO_LOCAL_DATE = "yyyy-MM-dd"

  /**
   * The ISO date format that formats or parses a ISO-8601 extended offset date with an offset, such
   * as '2011-12-03+01:00'.
   */
  ISO_OFFSET_DATE = "yyyy-MM-ddXXX"

  /**
   * The ISO time format that formats or parses a ISO-8601 extended local time without an offset,
   * such as '10:15:30'.
   */
  ISO_LOCAL_TIME = "HH:mm:ss"

  /**
   * The ISO time format that formats or parses a ISO-8601 extended local time without an offset,
   * such as '10:15'.
   */
  ISO_LOCAL_TIME_WITHOUT_SECONDS = "HH:mm"

  /**
   * The ISO time format that formats or parses a ISO-8601 extended offset time with an offset, such
   * as '10:15:30+01:00'.
   */
  ISO_OFFSET_TIME = "HH:mm:ssXXX"

  /**
   * The ISO time format that formats or parses a ISO-8601 extended offset time with an offset, such
   * as '10:15+01:00'.
   */
  ISO_OFFSET_TIME_WITHOUT_SECONDS = "HH:mmXXX"

  /**
   * The ISO date-time format that formats or parses a ISO-8601 extended offset date-time without an
   * offset, such as '2011-12-03T10:15:30'.
   */
  ISO_LOCAL_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ss"

  /**
   * The ISO date-time format that formats or parses a ISO-8601 extended offset date-time with an
   * offset, such as '2011-12-03T10:15:30+01:00'.
   */
  ISO_OFFSET_DATE_TIME = "yyyy-MM-dd'T'HH:mm:ssXXX"

  /**
   * The ISO date format that formats or parses the ISO-8601 extended ordinal date without an
   * offset, such as '2012-337'.
   */
  ISO_ORDINAL_DATE = "yyyy-DDD"

  /**
   * The ISO date format that formats or parses the ISO-8601 extended week-based date without an
   * offset, such as '2012-W48-6'.
   */
  ISO_WEEK_DATE = "yyyy-'W'ww-u"

  /**
   * The ISO date format that formats or parses a ISO-8601 basic local date without an offset, such
   * as '20111203'.
   */
  BASIC_ISO_DATE = "yyyyMMdd"

  /**
   * The RFC-1123 date-time format, such as 'Tue, 3 Jun 2008 11:05:30 GMT'. <p> This returns an
   * format capable of formatting and parsing most of the RFC-1123 format. RFC-1123 updates RFC-822
   * changing the year from two digits to four. This implementation requires a four digit year. This
   * implementation also does not handle North American or military zone names, only 'GMT' and
   * offset amounts. </p>
   */
  RFC_1123_DATE_TIME = "EEE, d MMM yyyy HH:mm:ss zzz"