Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite USKDateHint using Java 8 Date-Time APIs (fixing week hints) #1019

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 43 additions & 38 deletions src/freenet/client/async/USKDateHint.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package freenet.client.async;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.temporal.TemporalField;
import java.time.temporal.WeekFields;
import java.util.Arrays;
import java.util.Locale;
import java.util.TimeZone;

import freenet.keys.ClientSSK;
import freenet.keys.FreenetURI;
Expand All @@ -12,16 +14,13 @@

/** Utility class for date-based edition hints */
public class USKDateHint {

public enum Type {
YEAR,
MONTH,
DAY,
WEEK;

/** cached values(). Never modify or pass this array to outside code! */
private static final Type[] values = values();

public boolean alwaysMorePreciseThan(Type type) {
if(this.equals(type)) return false;
if(this.equals(DAY)) { // Day beats everything.
Expand All @@ -34,57 +33,63 @@ public boolean alwaysMorePreciseThan(Type type) {
return false;
}
}

private GregorianCalendar cal;

private USKDateHint() {
cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US);
private static final TemporalField WEEK_OF_YEAR = WeekFields.of(Locale.US).weekOfWeekBasedYear();
private static final TemporalField WEEK_YEAR = WeekFields.of(Locale.US).weekBasedYear();

private final LocalDate dateUtc;

USKDateHint(LocalDate dateUtc) {
this.dateUtc = dateUtc;
}

public static USKDateHint now() {
return new USKDateHint();
return new USKDateHint(LocalDate.now(ZoneOffset.UTC));
}

public String get(Type t) {
StringBuffer sb = new StringBuffer();
sb.append(cal.get(Calendar.YEAR));
if(t == Type.YEAR) return sb.toString();
if(t == Type.WEEK) {
sb.append("-WEEK-");
sb.append(cal.get(Calendar.WEEK_OF_YEAR));
public String get(Type type) {
if(type == Type.WEEK) {
return dateUtc.get(WEEK_YEAR) + "-WEEK-" + dateUtc.get(WEEK_OF_YEAR);
}

StringBuilder sb = new StringBuilder();
sb.append(dateUtc.getYear());
if (type == Type.YEAR) {
return sb.toString();
}
sb.append("-");
sb.append(cal.get(Calendar.MONTH));
if(t == Type.MONTH) return sb.toString();
sb.append("-");
sb.append(cal.get(Calendar.DAY_OF_MONTH));

sb.append('-');
sb.append(dateUtc.getMonthValue() - 1); // zero-indexed month
if(type == Type.MONTH) {
return sb.toString();
}

sb.append('-');
sb.append(dateUtc.getDayOfMonth());
return sb.toString();
}

/** Return the data to insert to each hint slot. */
public String getData(long edition) {
return "HINT\n"+Long.toString(edition)+"\n"+get(Type.DAY)+"\n";
return String.format("HINT\n%d\n%s\n", edition, get(Type.DAY));
}

static final String PREFIX = "-DATEHINT-";


/** Return the URL's to insert hint data to */
public FreenetURI[] getInsertURIs(InsertableUSK key) {
FreenetURI[] uris = new FreenetURI[Type.values.length];
int x = 0;
for(Type t : Type.values)
uris[x++] = key.getInsertableSSK(key.siteName+PREFIX+get(t)).getInsertURI();
return uris;
return Arrays.stream(Type.values())
.map(type -> key.getInsertableSSK(getDocName(key, type)).getInsertURI())
.toArray(FreenetURI[]::new);
}

/** Return the URL's to fetch hint data from */
public ClientSSK[] getRequestURIs(USK key) {
ClientSSK[] uris = new ClientSSK[Type.values.length];
int x = 0;
for(Type t : Type.values)
uris[x++] = key.getSSK(key.siteName+PREFIX+get(t));
return uris;
return Arrays.stream(Type.values())
.map(type -> key.getSSK(getDocName(key, type)))
.toArray(ClientSSK[]::new);
}

private String getDocName(USK key, Type type) {
return String.format("%s-DATEHINT-%s", key.siteName, get(type));
}

}
47 changes: 47 additions & 0 deletions test/freenet/client/async/USKDateHintTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package freenet.client.async;

import static freenet.client.async.USKDateHint.Type.DAY;
import static freenet.client.async.USKDateHint.Type.MONTH;
import static freenet.client.async.USKDateHint.Type.WEEK;
import static freenet.client.async.USKDateHint.Type.YEAR;
import static org.junit.Assert.assertEquals;

import java.time.LocalDate;

import org.junit.Test;

public class USKDateHintTest {

@Test
public void getYear() {
USKDateHint hint = new USKDateHint(LocalDate.parse("2023-06-01"));
assertEquals("2023", hint.get(YEAR));
}

@Test
public void getMonth() {
USKDateHint hint = new USKDateHint(LocalDate.parse("2023-06-01"));
assertEquals("2023-5", hint.get(MONTH));
}

@Test
public void getDay() {
USKDateHint hint = new USKDateHint(LocalDate.parse("2023-06-01"));
assertEquals("2023-5-1", hint.get(DAY));
}

@Test
public void getWeek() {
USKDateHint hintStartOfYear = new USKDateHint(LocalDate.parse("2023-01-01"));
USKDateHint hintEndOfYear = new USKDateHint(LocalDate.parse("2023-12-31"));
assertEquals("2023-WEEK-1", hintStartOfYear.get(WEEK));
assertEquals("2024-WEEK-1", hintEndOfYear.get(WEEK));
}

@Test
public void getData() {
USKDateHint hint = new USKDateHint(LocalDate.parse("2023-06-01"));
assertEquals("HINT\n12345\n2023-5-1\n", hint.getData(12345));
}

}