ID generation using AtomicLong, how to start from 0 each day - java

I am using java.util.concurrent.atomic.AtomicLong class to generate sequence numbers for id generation. I need to start this number from 1 each day what are the available logic, methods which I can use?

Here's an answer on how to get the beginning of a day using Joda Time. Then use the method AtomicLong#set(long) to reset the value.

Related

How to indicate some fields are not supported

Trying to move from Calendar to the new Java 8 time on Android. Is there a way to indicate that a time or date field is not supported? I can use the 'Truncate' method that will set all time fields of a shorter duration to zero, so a time stamp like 2020-09-30T10:37:15.345-04:00 can be truncated say at the minutes level. But that will leave 2020-09-30T10:00:00.00-04:00.
However, what I want to indicate is that the clock does not have minutes or less precision so that when one tries to read the minutes or seconds, there will be some indication that there are no such fields or that they are unknown. Zero is a valid value.
Right now in the Calendar case I have to add numerous methods to a class to indicate that. For example, I made a class called TimeStruct which wraps a Calendar. If I take a time stamp like 2020-10-01T04:55 it does not have minutes. So to keep that information I have a variable 'isSecondsSet' and set it to false. I create the Calendar from the elements I DO have. But as soon as I call something like Calendar.getTimeInMillis() the seconds and milliseconds fields get set to 0 and are indicated as set. So my additional variables let me know that there was no seconds field.
I was hoping that the new classes would no longer require me to keep my own indicators and I would also be able to parse something like 2020-10-01T04:55. I could not, but I could parse a full time stamp. So if I do that and truncate, can I indicate that the truncated fields are not supported? That way I wont use a value of 0 in the seconds.

Simple factory - checking data correctness

I have Month class which contains some data eg. number, number of days etc. I would like to create this class instance simply. I decided to create simple factory which contains months data and returns ready object. My question is where to check data correctness eg. January has 31 days and a couple others... Should Month class checks that data is correct or Factory should be responsible for it? (in this case we can create Month object with invalid data)...
Please don't reinvent calendar classes! Someone has already done it for you. Take a look at Joda-Time or the Java 8 package java.time. This are good starting points to learn how classes like Month should be designed.
The concepts of month and day of month shouldn't be mixed within a single class. Because how many days a month has depends on the year and the calendar system. The validation for invalid number of days should be done when you create a date from day of month, month and year. So it is part of the construction process of a date object.
This looks strange:
Month january = Month.newMonth(31);
The factory method which creates a Month object from an int should check if the parameter is in the range from 1 (January) to 12 (December) and return an enum representing the concrete month.
This is what I would expect:
Month january = Month.newMonth(1);
Your Month class should check this itself. It's always best practice to have the logic that is dependent only on the class in the class itself. Otherwise if someone else uses your application and instantiates a Month object without using the factory it will work, but it won't be what you as the designer intended.
You can handle an error however you like it, but I would do it in the constructor and then throw an error if someone tries instantiating it with invalid parameters.
You should validate the parameters before passing them in a constructor.
However a static factory method might not be the best place to validate input, if the input is dynamic and NOT done by you.
If you just want to make sure the compiler warns you if you use invalid parameters, you could throw a checked exception like this:
public static final Month newMonth(int numberOfDays) {
if(numberOfDays > 31 || numberOfDays < 28) {
throw new IllegalArgumentException("invalid numberOfDays");
}
return new Month(numberOfDays);
}
Either way, in my opinion, you should not go the try...catch way or make the constructor validate anything as it makes your code a lot less readable and also could break a lot of other code if you change your validation method.

Java: addToDay function

I'm trying to setup my addToDay function. I'm currently stuck on how to proceed with this or even write it correctly. The function itself will take a variable that ranges from -100 to 100. So you would basically add that variable to the current and if it was below the 0 then subtract a month or if it was above the months max day then add a month. Which i have that function setup so all i would have to do is call addToMonth with the correct amount. My problem lies within the amount of days each month has. For example, October has 31 days while November has 30. I have a function that will return the number of days in the current set month so i can call that to get how many max days should be in the current month. I'm thinking maybe a while loop would work but i just wanted to get anyone's thoughts on the best way to set it up.
I have 3 private ints: month, day, year. These are what need to be changed. I have both addTo functions for month and year setup already.
Here are some other functions i have created that can be used in this:
1. addToMonth(int delta) - changes the current month depending on the given parameter
2. getDaysInMonth() - will return the days in a month depending on the month itself
3. validateDay() - Will return true or false if the days fall outside the wanted requirements.
I don't want to use the calendar utility
I also don't want to use any other utilities. Just the base code with Junit for testing
Joda's plusDays() function and Java 8 LocalDate already has the logic that you are trying to achieve
Alright so i ended up just copying my original addToMonth function and modifying it abit to fit with days. So far it works but i do think it'll fail in the cases of different amounth of days not lining up.

Convert timestamp to weekNumber mapReduce

I am looking to preprocess timestamps to obtain the corresponding weeknumbers using mapreduce as the dataset has hundreds of millions of instances that need to be processed. I have so far figured out that the first MR job needs to preprocess and sort each line according to timestamp as the key and the rest of the line as value.
The second job then appends the corresponding date to each timestamp object.
I however do not know how to perform the third task I need to accomplish which is to create a continuous timeline of weeknumbers .Meaning, if my minimum timestamp corresponds to the date 03/10/2000 I would like to tag this with a number 10 (indicating that this is the 10th week of the year 2000 let's assume it is if its not in this case.). Then let's say I have the next timestamp corresponding to 02/01/2011, if we assume 52 weeks in the year 2000 and that 02/01/2011 is the 5th week in 2011, I would like to tag this date as week 57 and not as week 5. I would like to know how to achieve this last step in mapreduce. Assuming I have the following input file:
sorted_timestamp1::date::vals....
sorted_timestamp2::date::vals...
...
...
...
sorted_timestampn::date::vals.....
Simple pseudocode with map and reduce in java would suffice for my case, actual code would be great also.
Thanks in advance for your help!
I think you can separate the two problems:
1) map reduce logic:
What do you really want to calculate with map reduce. Depending on this information you have to choose the key values.
Just a guess from my side: If you want to do some aggregations on a weekly level, the mapper should take each line of input (think of line number as a key) and write out the data with new key representing the week (I'll give you some remarks in point 2.
The reducer will then have all data sets with equal week key in access and you can do whatever you want to do / aggregate and write the results out.
2) Week calculations:
Using java.util.Calendar object you can easily calculate the week of a Timestamp/Date. To get a continous week value you can calculate the week offset to a minimum reference date. To keep things simple I propose to use the 1.1. of a senceful date. To calculate the difference of weeks you can for example use
Joda package static method Weeks.weeksBetween
If the concrete value of the "week" key is not of special interest you can also use a composite key like
year*100+week
which is much simpler to evaluate and therefore is faster. If you really need the special week timeline think about using the simple key first (just used for aggregations in map reduce) and do the more expensive week timeline evaluations later after the reducer has generated its result with much less data.
Good luck + regards
Martin

Protocol Buffer: How to define Date type?

I'm trynig to write a proto file that has a Date field which is not defined as a type into Protocol buffer.
I have read the following post but I couldn't figure out a proper solution that suits me :
What the best ways to use decimals and datetimes with protocol buffers?.
I'm trying to convert the proto file to a java .
My answer in the linked post relates mainly to protobuf-net; however, since you are coming at this from java I would recommend: keep it simple.
For dates, I would suggest just using the time (perhaps milliseconds) into an epoch (1 Jan 1970 is traditional). For times, just the size in that same unit (milliseconds etc). For decimal, maybe use fixed point simply by scaling - so maybe treat 1.05 as the long 1050 and assert always exactly 3dp (hence fixed point).
This is simple and pragmatic, and covers most common scenarios without making things complicated.
I'm not sold on this idea, but I'm really not sold on the idea of storing dates (which aren't instants in time) as a timestamp, so here's my suggestion.
Convert your date into a human-readable integer (e.g. 2014-11-3 becomes 20141103) and store this integer value. It contains exactly the data you need, is simple to create and parse, and takes up minimal space. Additionally, it is ordered and has a one-to-one mapping of dates to valid values (granted, invalid numbers are possible, such as 20149999, but these are easy to detect). In contrast, there are approximately 86400 valid timestamps that represent each day.
NB: There is a discussion on DBA SE criticizing this method of date storage, but in that context a specialized date type exists, which obviously isn't the case here.

Categories

Resources