Поскольку вы упомянули, что используете ISO-8601 с типом данных String
, легко использовать сравнение операторы (<
, <=
и т. д.) в вашем условном выражении из-за лексикографического порядка, описанного в этом ответе.
Вот краткий пример, в котором я использовал время Java 8 и запускал его с DynamoDB Local:
import com.google.common.collect.ImmutableMap;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.util.Tables;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
public class DynamoDBStackoverflow {
public static final String TABLE_NAME = "exampleTable";
private static final String HASH_KEY = "hashAttributeName";
public static void main(String[] args) {
AWSCredentials awsCredentials = new BasicAWSCredentials("key", "secret");
AmazonDynamoDB client = new AmazonDynamoDBClient(awsCredentials);
client.setEndpoint("http://localhost:4000");
DynamoDB dynamoDB = new DynamoDB(client);
if (Tables.doesTableExist(client, TABLE_NAME)) {
client.deleteTable(TABLE_NAME);
}
final CreateTableRequest createTableRequest = new CreateTableRequest()
.withTableName(TABLE_NAME)
.withKeySchema(new KeySchemaElement(HASH_KEY, KeyType.HASH))
.withAttributeDefinitions(new AttributeDefinition(HASH_KEY, ScalarAttributeType.S))
.withProvisionedThroughput(new ProvisionedThroughput(15L, 15L));
final Table table = dynamoDB.createTable(createTableRequest);
final Instant now = Instant.now();
final Instant before = now.minus(10, ChronoUnit.MINUTES).truncatedTo(ChronoUnit.MINUTES);
final Instant after = now.plus(10, ChronoUnit.MINUTES);
System.out.println("Before: " + before.toString());
System.out.println("Now: " + now.toString());
System.out.println("After: " + after.toString());
table.putItem(new Item().withPrimaryKey(HASH_KEY, "1")
.withString("dateField", before.toString()));
table.putItem(new Item().withPrimaryKey(HASH_KEY, "2")
.withString("dateField", now.toString()));
System.out.println("put items");
table.scan().forEach(System.out::println);
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
.withConditionExpression("dateField < :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
throw new RuntimeException();
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("expected conditional write with < to fail when they are equal");
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
.withConditionExpression("dateField < :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
throw new RuntimeException();
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("expected conditional write with < to fail when new is before");
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "1")
.withConditionExpression("dateField <= :beforeDate")
.withValueMap(ImmutableMap.of(":beforeDate", before.toString()))
.withUpdateExpression("SET dateField = :beforeDate");
try {
table.updateItem(updateItemSpec);
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("should not happen");
throw new RuntimeException();
}
updateItemSpec = new UpdateItemSpec().withPrimaryKey(HASH_KEY, "2")
.withConditionExpression("dateField <= :afterDate")
.withValueMap(ImmutableMap.of(":afterDate", after.toString()))
.withUpdateExpression("SET dateField = :afterDate");
try {
table.updateItem(updateItemSpec);
} catch (ConditionalCheckFailedException ccfe) {
System.out.println("should not happen");
throw new RuntimeException();
}
System.out.println();
System.out.println("after all updates");
table.scan().forEach(System.out::println);
}
}
И вывод:
Before: 2015-06-08T15:57:00Z
Now: 2015-06-08T16:07:08.893Z
After: 2015-06-08T16:17:08.893Z
put items
{ Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} }
{ Item: {hashAttributeName=2, dateField=2015-06-08T16:07:08.893Z} }
expected conditional write with < to fail when they are equal
expected conditional write with < to fail when new is before
after all updates
{ Item: {hashAttributeName=1, dateField=2015-06-08T15:57:00Z} }
{ Item: {hashAttributeName=2, dateField=2015-06-08T16:17:08.893Z} }
person
mkobit
schedule
08.06.2015
String
или используетеNumber
с разницей во времени? (как из эпохи)? - person mkobit   schedule 05.06.2015