How to define a class that represents an age group? - date-range

I need to be able to define various age groups, i.e. 10 - 11, 12 - 13, etc.
How can I represent an AgeGroup class such that that the age can appropriately group people together today, tomorrow, and in the future, i.e. today's 11 year old could 12 tomorrow (in which case he would be grouped into the 12-13 group instead of the 10-11 year old group, as he was yesterday).
So far I have this:
public class AgeGroup
{
public string Name { get; protected set; }
public DateRange BirthDateRange { get; protected set; }
public Guid Id { get; protected set; }
public Status Status { get; protected set; }
public virtual DateRange ApplicableDateRange { get; set; }
public AgeGroup(Guid id, string name, DateRange birthDateRange,DateRange applicableDateRange)
{
Id = id;
Name = name;
Status = status;
BirthDateRange = birthDateRange;
ApplicableDateRange = applicableDateRange;
}
}
public class DateRange
{
public DateRange(DateTime startDate, DateTime endDate)
{
StartDate = startDate;
EndDate = endDate;
}
DateTime _startDate;
DateTime _endDate;
public virtual DateTime StartDate
{
get { return _startDate; }
set { _startDate = value.ToUniversalTime(); }
}
public virtual DateTime EndDate
{
get { return _endDate; }
set { _endDate = value.ToUniversalTime(); }
}
}
This class defines a range of time where this agegroup is applicable. When the applicable date range is passed, we would need to shift everything in time. But is there a better way to do this?

If you're thinking of storing the age range within a person object of some description, I wouldn't, since (1) it's an easily calculable value from the birth date; and (2) it's not really a property of the object (it could be considered so but its transient nature will make things more complex than need be).
Instead, store only the birth date then provide some code which can give an age range based on that birth date and the current date.
You can still have age ranges but the people themselves do not exist "inside" them. Instead, you would be able to pass a person object to a function and have it give you back the relevant range.
And, if possible, the age ranges should be based on ages rather than birth dates, since the former is unchanging - you don't have to "move" objects between ranges since that's automatic when their range is calculated from their birth date and the current date.
If that's not possible (and it appears from your supplied chart that it may be difficult):
then you can use birth dates as you currently are but with a slight modification to allow for things to change year to year.
Have a season object which has the following fields:
Start date.
A collection of range objects.
This will allow you to have multiple season objects if, for example, the age ranges change in following years. As long as they don't change, you'll only have a single season object with a start date of whenever your 2014/15 season starts.
The range objects themselves are then a collection of objects of the form:
Start birth date End birth date Range name
---------------- -------------- ----------
1993-01-01 1993-07-31 U22
1993-08-01 1994-07-31 U21
1994-08-01 1995-07-31 U20
:
2009-08-01 2010-07-31 U5
2010-08-01 2010-12-31 U4
Then, in order to find out which age group someone belongs to, you:
Find the current season object, based on the date of the season (usually today, though it's conceivable you may want to look at earlier seasons as well).
Go through all the range objects for that season until you find one where the persons birth date falls between the start and end dates for the range. If you don't find an eligible range, then they're not allowed to play.
Then extract the range name.

Related

Search date period in DB (month and year columns)

Here's my Dto:
export class GetQuotaQuery {
#Matches(
/^(0[1-9]|1[0-2])-(20[0-9]{2})$/,
{
message:
"Date format of 'from' field should be MM-YYYY (Month between 01 and 12, Year 2000 to 2099)"
}
)
from: string;
#Matches(
/^(0[1-9]|1[0-2])-(20[0-9]{2})$/,
{
message:
"Date format of 'to' field should be MM-YYYY (Month between 01 and 12, Year 2000 to 2099)"
}
)
to: string;
}
I will receive a string representing a date in the format MM-YYYY on parameters from and to, and I need to use those to query objects in the database matching that period.
The database doesn't use a datetime column, but two separated integer columns: month and year. As below:
What's the best way to achieve that?
REMARK: Changing the database columns type is not an option as I have no control over that. Thanks in advance.

How to store and read millions of records in Azure with secondary indexing

I need to store tens of millions of records in Azure. I need to be able to sort them by insert date in descending order. Finally, I need to issue where clauses on 3 fields.
public class Record
{
public DateTime CreatedOn {get; set;}
public string Filter1 {get; set;}
public string Filter2 {get; set;}
public bool Filter3 {get; set;}
}
I believe Azure Table Storage does not support secondary indexes, so I'm considering CosmosDB. The problem is each logical partition on CosmosDB is limited to 20 GBs. I can't dump everything in a single partition. I'm thinking of slicing data horizontally based on the CreatedOn field (dd/mm/yyyy without the time component). This helps me distribute the data, but I'm stuck with the query part to read it back.
The data is user generated; thus, I have no idea what values CreatedOn will be assigned. If I partition on CreatedOn, how can I make my query smart so that I know what the next partition key is when I reach the end of the previous partition?
Example:
Record1 CreatedOn => 5/28/2020
Record2 CreatedOn => 5/28/2020
Record3 CreatedOn => 5/22/2020
Record4 CreatedOn => 5/10/2020
There could be a large gap between dates, so I don't want to brute force the next partition by scanning the range day by day.
Regarding queries:
Filter1 and Filter2 can have 5 and 12 different values respectively. Filter3 is just a boolean.
A sample query would look like:
select top 20 from record
where Filter1 = 'Value1' and Filter2 = 'Value2' and Filter3 = false
order by CreatedOn desc
Another sample query is the same as above without Filter2.
select top 20 from record
where Filter1 = 'Value1' and Filter3 = false
order by CreatedOn desc
Use Cosmos SQL API. You can use Order by to sort on query.
All the fields are indexed by default. You can customize the indexing policy to include composite indices to make queries more efficient.
Pick a PK which will have a wide range of possible values to spread the request unit (RU) consumption and data storage evenly across all logical partitions evenly. Also, you should know the PK value for majority of your queries. You will use it in you where clause so that the query engine will only query specific partitions where the data of interest resides.
In you case what should be that PK property?
public class Record
{
public DateTime CreatedOn {get; set;}
public string Filter1 {get; set;}
public string Filter2 {get; set;}
public bool Filter3 {get; set;}
}
"CreatedOn" is not a good choice. First, like you mentioned you would not know its value during query time, so you will have to always do cross partition queries. Second, all your writes for a given day will go to the same partition resulting in hot partition which will result in rate-limiting and in inefficient use of the provisioned throughput, and higher costs.
Do any of the other properties help the cause? Maybe you must create another property. Maybe UserID , I am just making one up since I don’t know the context.
public class Record
{
public DateTime CreatedOn {get; set;}
public string Filter1 {get; set;}
public string Filter2 {get; set;}
public bool Filter3 {get; set;}
public string UserID {get; set;}
}
Now you can query
select top 20 from record
where Filter1 = 'Value1' and Filter2 = 'Value2' and Filter3 = false and UserID = 'somevalue' order by CreatedOn desc

How to do a timestamp query in Firestore

i would like to know how to structure a timestamp field in Firestore in order to do specific queries like:
Get all the documents with the same hour in a month
Retrieve timestamp from firebase and compare with required hour.If document matches add the document to an array.Finally after comparing with all documents your array contains only documents with same hour in a month
Date month = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(month.getTime());
calendar.add(Calendar.MONTH, -6);
final String date = String.valueOf(document.get("OrderPlacedDateTime"));
if(date.contains((CharSequence) year)) {
//add to array
}
I did this in android idea might be helpful.

assign default value to DateTime property in table entity of azure storage table

How can I assign default value to DateTime property in table entity of Azure Storage Table.
I am trying the code below, but I'm not able to set value (throwing an error from Azure Table while inserting, as DateTime taking has 1/1/0001).
[DefaultValue(DateTime.Now]
public DateTime LastUpdate { get; set; }
As Per msdn, the value that can go in datetime property is "A 64-bit value expressed as Coordinated Universal Time (UTC). The supported DateTime range begins from 12:00 midnight, January 1, 1601 A.D. (C.E.), UTC. The range ends at December 31, 9999."
So you cannot assign DateTime.MinValue. Lowest you can store is new DateTime(1601, 1, 1)
As mentioned by #Aravind in the answer, minimum value for DateTime type attribute supported by Azure Tables is Jan 1, 1600 UTC. Thus setting the default value to DateTime.MinValue will result in an error.
One possible solution for you is to keep this attribute nullable in your model.
public DateTime? LastUpdate { get; set; }
So, when no value is supplied the default value for this would be null. You would need to remove DefaultValue attribute as mentioned in comments above.

How do you choose the last string in a String value?

There are two tables:
Student(sid integer, sname varchar(20), programme varchar(4), level integer, age integer)
Tutor(tid integer, tname varchar(20))
The task is to find the names of all IT students who are enrolled in a class taught by a tutor whose surname is Hoffman.
This is what I have so far:
SELECT s.sname
FROM student s, tutor t
WHERE s.programme = 'IT' AND t.tname = '%Hoffman';
However, the '%Hoffman' part will only search for a string which contains 'Hoffman', so technically if if there would be anyone with Hoffman as the first name, the query will return his data too.
The tname column is of type String and consist of a first name, a space, and a last name, and possible middle names in between.
How do you choose the last string (or index?) of a value in t.tname in this case?
You could use something like this:
WHERE s.programme = 'IT' and RIGHT(t.tname, 7)
since 'Hoffman' has 7 characters

Resources